Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] enable thread safety (zts) for apache images; drop zts images #742

Open
yosifkit opened this issue Nov 10, 2018 · 12 comments
Open

[RFC] enable thread safety (zts) for apache images; drop zts images #742

yosifkit opened this issue Nov 10, 2018 · 12 comments

Comments

@yosifkit
Copy link
Member

If we add --enable-maintainer-zts to the PHP_EXTRA_CONFIGURE_ARGS then all three Apache MPMs become available: prefork, worker, and event.

tests:

Apache will start with any of the three MPMs (used event as default).

diff --git a/apache-Dockerfile-block-1 b/apache-Dockerfile-block-1
index a8e0078..630d13c 100644
--- a/apache-Dockerfile-block-1
+++ b/apache-Dockerfile-block-1
@@ -29,9 +29,6 @@ RUN set -ex \
                && chown -R "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
        done
 
-# Apache + PHP requires preforking Apache for best results
-RUN a2dismod mpm_event && a2enmod mpm_prefork
-
 # logs should go to stdout / stderr
 RUN set -ex \
        && . "$APACHE_ENVVARS" \
@@ -56,4 +53,4 @@ RUN { \
        && a2enconf docker-php
 
 ENV PHP_EXTRA_BUILD_DEPS apache2-dev
-ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
+ENV PHP_EXTRA_CONFIGURE_ARGS --disable-cgi --enable-maintainer-zts --with-apxs2
$ docker run -it --rm df3a4c6a986d
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat Nov 10 00:37:02.664991 2018] [mpm_event:notice] [pid 1:tid 139860600038592] AH00489: Apache/2.4.25 (Debian) PHP/7.2.12 configured -- resuming normal operations
[Sat Nov 10 00:37:02.665019 2018] [core:notice] [pid 1:tid 139860600038592] AH00094: Command line: 'apache2 -D FOREGROUND'
^C[Sat Nov 10 00:37:03.766817 2018] [mpm_event:notice] [pid 1:tid 139860600038592] AH00491: caught SIGTERM, shutting down
$ docker run -it --rm df3a4c6a986d bash -c 'a2dismod mpm_event && a2enmod mpm_worker && exec docker-php-entrypoint apache2-foreground'
Module mpm_event disabled.
To activate the new configuration, you need to run:
  service apache2 restart
Considering conflict mpm_event for mpm_worker:
Considering conflict mpm_prefork for mpm_worker:
Enabling module mpm_worker.
To activate the new configuration, you need to run:
  service apache2 restart
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat Nov 10 00:37:13.585052 2018] [mpm_worker:notice] [pid 1:tid 140705571566784] AH00292: Apache/2.4.25 (Debian) PHP/7.2.12 configured -- resuming normal operations
[Sat Nov 10 00:37:13.585089 2018] [core:notice] [pid 1:tid 140705571566784] AH00094: Command line: 'apache2 -D FOREGROUND'
^C[Sat Nov 10 00:37:14.935140 2018] [mpm_worker:notice] [pid 1:tid 140705571566784] AH00295: caught SIGTERM, shutting down
$ docker run -it --rm df3a4c6a986d bash -c 'a2dismod mpm_event && a2enmod mpm_prefork && exec docker-php-entrypoint apache2-foreground'
Module mpm_event disabled.
To activate the new configuration, you need to run:
  service apache2 restart
Considering conflict mpm_event for mpm_prefork:
Considering conflict mpm_worker for mpm_prefork:
Enabling module mpm_prefork.
To activate the new configuration, you need to run:
  service apache2 restart
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat Nov 10 00:37:29.323216 2018] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/7.2.12 configured -- resuming normal operations
[Sat Nov 10 00:37:29.323244 2018] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
^C[Sat Nov 10 00:37:30.249286 2018] [mpm_prefork:notice] [pid 1] AH00169: caught SIGTERM, shutting down

We'll leave the default on the current mpm_prefork and note how to swap:

FROM php:7.2-apache
RUN a2dismod mpm_prefork && a2enmod mpm_event
# also a simple one line docker run:
# docker run ... php:7.2-apache bash -c 'a2dismod mpm_prefork && a2enmod mpm_event && exec docker-php-entrypoint apache2-foreground'

We should also be able to do away with the plain -zts variants, since the cli can still be found in the apache image.


What effect will this have on Apache mpm_prefork?

Should we later migrate to mpm_event?

Other questions, concerns?


notes:

  • this is unrelated to pthreads
  • maker of pthreads with some misconceptions: reddit
@tianon
Copy link
Member

tianon commented Nov 10, 2018

Oh nice; IMO this makes a ton of sense. Does PHP recommend one MPM or another, all other things being equal?

We can also make zts an alias for apache in the tags to make this more obvious and hopefully affect less users negatively. 👍

@XzenTorXz
Copy link

The HTTP/2 guide states:

If your setup can handle it, configuring event mpm is nowadays the best one (if supported on your platform). [src]

So atleast apache recommends mpm_event

@tianon
Copy link
Member

tianon commented Nov 27, 2018

https://www.reddit.com/r/PHP/comments/1jo517/multithreading_in_php_with_pthreads/cbhb3ix/ is interesting here -- there's definitely a performance decrease with simply enabling ZTS, and it's non-negligible (I've reproduced those tests, and my machine is significantly faster so the numbers are much lower, but it's still enough difference to make me anxious).

I'm also worried about performance more than usual due to the resurgence of interest on #493, specifically the link to https://medium.com/@uv_d/migrating-our-php-applications-to-docker-without-sacrificing-performance-1a69d81dcafb which shows pretty clearly that we've already got some performance issues compared to Debian that I think we need to dig into and figure out what we're doing different.

@tianon
Copy link
Member

tianon commented Nov 27, 2018

In researching more, I found https://blog.remirepo.net/post/2017/11/17/Fedora-27-changes-in-http-and-php (which is interesting by itself), but it links to https://secure.php.net/manual/en/install.unix.apache2.php which has the following warning:

Warning We do not recommend using a threaded MPM in production with Apache 2. Use the prefork MPM, which is the default MPM with Apache 2.0 and 2.2. For information on why, read the related FAQ entry on using Apache2 with a threaded MPM

And from that final link (https://secure.php.net/manual/en/faq.installation.php#faq.installation.apache2):

If you want to use a threaded MPM, look at a FastCGI configuration where PHP is running in its own memory space.

So the official PHP upstream recommendation is to not use mpm_event, and to instead use PHP-FPM, which is interesting.

@tianon
Copy link
Member

tianon commented Nov 27, 2018

(And of course, our own issue about PHP-FPM plus ZTS, #249, which links to https://github.com/krakjoe/pthreads#sapi-support)

@rvdlee-salesupply
Copy link

Related issue #249 is actually something I'm looking into right now. We have a Zend Application with some console commands that we would like to run through ZTS, while FPM normally deploys with NTS. I understand the use of these versions.

It would've been nice though if there was an image already prepped that contained a executable for ZTS and NTS + FPM for these kind of applications. In #249 the user @j4r3kb is trying to do exactly the same as what I'm trying to realize.

@mildsunrise
Copy link

Since PHP's official recommendation with threaded MPMs is to use FPM instead of mod_php, and distributions have switched to this setup, would a PR for an apache-fpm variant be accepted?

It'd be a drop-in replacement for apache, with the limitations of the FPM setup: php_value / php_flag directives not supported in .htaccess or Apache config.

WDYT?

@tianon
Copy link
Member

tianon commented Jan 16, 2019

I'm definitely not keen on seeing more variants here -- we're already pretty out of control here. 😕 😞

@mildsunrise
Copy link

Yes, I understand. There's an easier alternative, we can include FPM in apache too, and provide an alternate entrypoint that starts both Apache and FPM. The user can then switch from mod_php to FPM by doing:

RUN a2dismod mpm_prefork php7 && a2enmod mpm_event mod_proxy
CMD ["apache-fpm"]

This gets us the best of both worlds: no performance penalty, while keeping one variant. The only drawback I see is increased image size.

@tianon
Copy link
Member

tianon commented Jan 21, 2019

Interesting idea!

I did a really rough build test, and it appears the size difference is ~15MB to enable FPM in the Apache build (~376MB before, ~391MB after), which seems pretty reasonable IMO.

We could probably do that slightly simpler by crafting a configuration file that allows us to simply swap by providing a -D or an environment variable to our apache2 launch so that users wouldn't have to do a2enmod/a2dismod directly. 🤔

@mildsunrise
Copy link

Great, I'll start working on it.

@mildsunrise
Copy link

We could probably do that slightly simpler by crafting a configuration file that allows us to simply swap by providing a -D or an environment variable to our apache2 launch so that users wouldn't have to do a2enmod/a2dismod directly.

I thought of it (I planned to use -D to change SetHandler for FPM) but a2enmod/a2dismod create/remove symlinks, so it's not really configuration files. If we want to control modules via -D or an environment variable, I think we'd have to mess with Debian's module loading system thing. Not sure though.

Maybe we could simply add those a2enmod / a2dismod commands to the entrypoint (apache-fpm), so that only CMD ["apache-fpm"] is required in the Dockerfile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants