rfc:socketactivation
Differences
This shows you the differences between two versions of the page.
rfc:socketactivation [2012/10/18 18:59] davidstrauss [Request for Comments: systemd socket activation support for PHP-FPM] |
rfc:socketactivation [2017/09/22 13:28] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Request for Comments: systemd socket activation support for PHP-FPM ====== | ||
- | * Version: 1.0 | ||
- | * Date: 2012-10-17 | ||
- | * Author: David Strauss <david@davidstrauss.net>, Jerry Blakley <jerry@getpantheon.com> | ||
- | * Status: Under Discussion | ||
- | * First Published at: http://wiki.php.net/rfc/socketactivation | ||
- | * Patches: [[rfc/socketactivation/build.patch|build.patch]] (needs to be made optional), [[rfc/socketactivation/activate.patch|activate.patch]] | ||
- | ===== Introduction ===== | ||
- | |||
- | Linux distributions with systemd support a "socket activation" feature that allows systemd to listen on the socket from early in the boot process and start the service when the first client connects. Supporting this in PHP-FPM is beneficial to systems with many pools (so they can start on-demand), for administrators that prefer to have a PHP-FPM pool listen on a privileged port or path without having to start it initially as root, and for administrators wanting to resolve a dependency between the web server accepting requests and PHP-FPM's socket being able to queue or service them. | ||
- | |||
- | launchd and legacy internet superservers support socket activation in similar ways. | ||
- | |||
- | Socket activation creates no overhead once the daemon has started. systemd does not proxy any traffic; it just hands over the file descriptor. Once the daemon is running and using the systemd-provided socket(s), there's no distinction in daemon operation until shutdown, where it skips closing the socket(s). | ||
- | |||
- | ===== Implementation details ===== | ||
- | |||
- | When systemd starts a socket-activated service, it passes the bound, listening socket in as a file descriptor. PHP-FPM is already accustomed to such behavior using the FPM_SOCKETS environmental variable. It's actually possible to "socket activate" PHP-FPM //once// by setting it cleverly (so that it looks for the file descriptor(s) created by systemd). Unfortunately, PHP-FPM's shutdown behavior leaves the systemd socket in a state that's unusable for subsequent activations. | ||
- | |||
- | It's possible to provide reliable socket activation support by having a loop before or after the "import inherited sockets" one in fpm_sockets_init_main(). The loop can either inspect the environmental variables systemd sends in directly or call the reference implementations defined in systemd/sd-daemon.h. Jerry and I have a patch working with the latter approach, including the necessary linking against systemd's library. (Linking is also desirable to ease adding support later for sd_notify(), which can inform systemd of PHP-FPM's current lifecycle status, including startup, reloading, and shutdown.) | ||
- | |||
- | Adding the support also requires marking the systemd-imported sockets as persistent past shutdown so PHP-FPM does not perform various cleanup actions on them that break subsequent activations of the service. | ||
- | |||
- | If systemd socket activation support isn't enabled at build time, this feature will have no effect. Even if this feature is enabled for a build, it will have no effect on non-users of socket activation. | ||
- | |||
- | ===== Usage for end-users ===== | ||
- | |||
- | The recommended use for PHP-FPM with socket activation is a 1:1:1 relationship between the listening socket unit in systemd, the service unit in systemd, and the PHP-FPM pool. This approach allows each pool to spawn on-demand. It also has nice effects like allowing cgroups resource limitations (like CPU shares, memory, block I/O, and network I/O) and security isolations (like PrivateTmp and syscall restrictions) to be set per-pool in the corresponding systemd service unit. Logs will also aggregate per-pool in the systemd journal for the corresponding service. | ||
- | |||
- | Here's an example configuration. It's still possible to have PHP-FPM drop its own permissions or have it perform its own daemonization fork, but it's unnecessary. It's also possible to directly start the PHP-FPM pool without waiting for the first incoming connection; systemd will still start the necessary socket and pass it in. | ||
- | |||
- | ====/etc/systemd/system/my-php-fpm-pool.socket ==== | ||
- | |||
- | <file> | ||
- | [Socket] | ||
- | ListenStream=/var/run/my-php-fpm-pool.socket | ||
- | |||
- | [Install] | ||
- | WantedBy=sockets.target | ||
- | </file> | ||
- | |||
- | ==== /etc/systemd/system/my-php-fpm-pool.service ==== | ||
- | |||
- | <file> | ||
- | [Service] | ||
- | User=my-php-fpm-pool | ||
- | Group=my-php-fpm-pool | ||
- | ExecStart=/usr/sbin/php-fpm --fpm-config=/etc/php-fpm.d/my-php-fpm-pool.conf | ||
- | KillMode=process | ||
- | </file> | ||
- | |||
- | ==== /etc/php-fpm.d/my-php-fpm-pool.conf ==== | ||
- | |||
- | <file> | ||
- | [global] | ||
- | pid = /var/run/my-php-fpm-pool.pid ; Not really used by anything with daemonize = no. | ||
- | error_log = syslog ; Will aggregate to the service's systemd journal. | ||
- | daemonize = no ; systemd handles the forking. | ||
- | |||
- | [www] | ||
- | listen = /var/run/my-php-fpm-pool.socket ; Must match systemd socket unit. | ||
- | user = my-php-fpm-pool ; Ignored but required. | ||
- | group = my-php-fpm-pool ; Ignored but required. | ||
- | pm = static | ||
- | pm.max_children = 10 | ||
- | slowlog = syslog | ||
- | </file> | ||
- | |||
- | ==== Enabling the pool ==== | ||
- | |||
- | <code> | ||
- | systemctl enable my-php-fpm-pool.socket # Enables the socket at system startup. | ||
- | systemctl start my-php-fpm-pool.socket # Starts the socket listening. | ||
- | </code> | ||
- | ===== Changelog ===== | ||
- | |||
- | 2012-10-17: Initial version. |
rfc/socketactivation.txt · Last modified: 2017/09/22 13:28 (external edit)