简体   繁体   中英

Get the PHP-FPM timeout limit in script

I am developing on a vagrant box on PHP 5.6.26 with FPM.

I was working on a test battery to hit a REST endpoint with a series of requests, to try to capture intermittent errors on the remote side. In my battery, I had a variable for the number of repetitions to run. Because I could not know how long each request would take, sometimes a large number of repetitions would cause the script to time out, and I wouldn't be able to see the results of the requests that had run.

So instead of specifying repetitions, I decided to maximize the test runs. I monitored how long script execution had gone on, and tried to bail if we were getting close to the timeout, using ini_get('max_execution_time') .

However, I noticed with this method, I wasn't getting nearly as many test runs as I had previously. I did more debugging, and I found that I could exceed max_execution_time!

I did some more looking, and discovered that PHP-FPM has its own timeout limit, and I was hitting that one when my script was dying:

[Fri Oct 28 19:41:04.491557 2016] [proxy_fcgi:error] [pid 2343:tid 140619049568000] (70007)The timeout specified has expired: [client 192.168.253.1:52431] AH01075: Error dispatching request to :, referer: http://local.mysite.com/test

So, knowing that I want to run tests as long as I'm allowed, how do I get the actual timeout value from PHP-FPM inside my script?

I know there are settings in /etc/php-fpm.d/www.conf , but I don't want to hard-code that value in my script, in case it changes.

In short, use getrusage() , not time() .

A bit more now. The script execution time that is limited by max_execution_time is the time spent inside the script. From the set_time_limit doc , second note :

Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.

The simplest example : sleep(35) with max_execution_time = 30 is ok, as you already noticed.

If you use time() , you will always end after 30 real world seconds, even if you still had time for the script.

So you will need real time in script, not real world time. To get to this kind of time you have the function getrusage() and its answer ru_utime.tv_sec and ru_utime.tv_usec keys.

Second step, as you are using the PHP-FPM, it is the same process that answers multiple requests. This means one process will carry over from one request to an other the statistics for those ru_utime . You will have to get the ru_utime.tv_sec value at script begin and compute the difference. When this difference come near to the max_execution_time you can end the repetitions/loops.

Something like :

$gru = getrusage();
$gru_start = $gru['ru_utime.tv_sec'];
$gru_end = $gru_start;

// Considering that duration of one iteration in
// the next while loop is less than 1 second,
// we use this as the max limit.
$max_time = ini_get('max_execution_time') - 1;

while ($gru_end - $gru_start < $max_time) {
    // long and repetitives tasks
    // ....

    // could use a counter to not call this function at each iteration,
    // but only once every 10, 100, 1000 ... times.
    $gru = getrusage();
    $gru_end = $gru['ru_utime.tv_sec'];
}

Or transform it into a function...

Hope it brings you further. To be honest, I'm a bit at the limit of my understanding here, and this solution could be a bit fragile, use with appropiate care.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM