Increase PHP-FPM idle timeout setting

2019-03-26 16:30发布

问题:

We have recently migrated to PHP-FPM. However we have encountered a problem with some long running scripts. The code looks roughly like:

foreach ($items as $item) {
     set_time_limit(30);
     proccessThatTakesAround2secs(); 
}

The normal PHP script time limit is also 30 secs. This was previously working fine in that we reset the remaining time limit back to 30 secs for each item. There are around 1000 items meaning the script in total would normally take about 30 mins to complete. However we have since reached the following problem:

FastCGI: comm with server "/usr/local/php-5.6.24/sbin/php5-fpm" aborted: idle timeout (30 sec)

Now my question is, is it sensible to increase the idle timeout to something like an hour but still ensure the PHP scripts don't run for longer than 30 secs, unless we use set_time_limit? Is there a way to set the idle timeout on a per script basis (something akin to a set_time_limit?)

Here is our pool configuration:

[www]
user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = static
pm.max_children = 55
pm.max_requests = 10000

php_value[memory_limit] = 128M
php_value[max_execution_time] = 30
php_value[upload_max_filesize] = 20M
php_value[post_max_size] = 20M
php_value[max_input_vars] = 9999

And here is our fastcgi.conf

<IfModule mod_fastcgi.c>
    AddType application/x-httpd-fastphp5 .php
    Action application/x-httpd-fastphp5 /php5-fcgi
    Alias /php5-fcgi /usr/local/php-5.6.24/sbin/php5-fpm
    FastCgiExternalServer /usr/local/php-5.6.24/sbin/php5-fpm -socket /var/run/php5-fpm.sock -idle-timeout 30 -pass-header Authorization
    <Directory /usr/local/php-5.6.24/sbin/>
        Require all granted
   </Directory>
</IfModule>

回答1:

I have found my self in similar situation with long running processes and php-fpm and fastcgi when migrated from mod_php.

The error you are seeing is from apache's fastcgi proxy who killed connection to php-fpm pool because your script did not outputted anything for 30 seconds.

You can change idle-timeout in your apache config to extend it (cannot be 0):

FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -socket /run/php/php7.0-fpm.sock -idle-timeout 1800 -pass-header Authorization

Chain goes like this: Apache -> FastCgiExternalServer proxy -> php-fpm pool server -> php process

Apache proxy kills connection to php, so setting max_execution_time or set_time_limit from php doesn't matter.

AFAIK if php is being run on Apache via mod_fastcgi, there is no way to set per script time limits from php code or .user.ini or via apache (.htaccess). So that means that by extending it in one place you are extending timeout for eg. both your frontend and backend users. Alternatively you could separate it via 2 vhosts and define different timeout values there.



回答2:

While this doesn't necessarily fit the OP's configuration, most people are going to be running PHP-FPM under a proxy setting. As such, you can set the timeout for a proxy setup like so (this is my php.conf)

<Proxy "fcgi://127.0.0.1:9000">
   ProxySet timeout=300
</Proxy>

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
    SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>

If you're using a .sock file instead, just replace both instances of fcgi://127.0.0.1:9000 with the command to use the sock file