Hi all!
I am optimizing a few of the PHP scripts by:
- doing all that generates output to browser
- closing connection to browser
- doing some more processing
The processing bit cannot be avoided, but the speed of execution (from
visitors' point of view) is awesome this way. The problem is that we
have tried migrating the script to NginX + FastCGI (it works on Apache +
mod_php) but it doesn't close the connection anymore, it keeps it open
until the end... Which makes scripts slow again.
I am using Content-Length to allow server to figure out that all content
was already generated. This is the test case:
<?
header("Connection: close"); // not sure we need this one
header("Content-Encoding: none");
ignore_user_abort(true);
ob_start();
echo ('Lets output something.');
// output Content-Length and flush buffers:
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
// ****************
// do some heavy processing here:
sleep(5);
function postproc() {
flush();
sleep(5);
}
register_shutdown_function('postproc');
?>
The browser shows this page immediately in Apache+mod_php but it waits
for 10 seconds in NginX + FastCGI.
I am a bit stuck here and would appreciate some help... Is this a
problem with FastCGI? Is there another way to do it?
Thanks!
Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,51310,51310#msg-51310
on 2010-02-06 11:01
on 2010-02-06 16:25
Hi, I just tested your script and found that I needed to wait 10s to see the response. I am using Windows XP, Apache 2.1.11 worker MPM, PHP 5.3.1 It did not work asynchronously as you expected. Am I missing something here? Regards cactus wrote: > Hi all! > > I am optimizing a few of the PHP scripts by: > - doing all that generates output to browser > - closing connection to browser > - doing some more processing > > The processing bit cannot be avoided, but the speed of execution (from > visitors' point of view) is awesome this way. The problem is that we > have tried migrating the script to NginX + FastCGI (it works on Apache + > mod_php) but it doesn't close the connection anymore, it keeps it open > until the end... Which makes scripts slow again. > > I am using Content-Length to allow server to figure out that all content > was already generated. This is the test case: > > <? > header("Connection: close"); // not sure we need this one > header("Content-Encoding: none"); > ignore_user_abort(true); > ob_start(); > > echo ('Lets output something.'); > > // output Content-Length and flush buffers: > $size = ob_get_length(); > header("Content-Length: $size"); > ob_end_flush(); > flush(); > > // **************** > // do some heavy processing here: > sleep(5); > > function postproc() { > flush(); > sleep(5); > } > register_shutdown_function('postproc'); > ?> > > > The browser shows this page immediately in Apache+mod_php but it waits > for 10 seconds in NginX + FastCGI. > > I am a bit stuck here and would appreciate some help... Is this a > problem with FastCGI? Is there another way to do it? > > Thanks! > > Posted at Nginx Forum: > http://forum.nginx.org/read.php?2,51310,51310#msg-51310
on 2010-02-07 15:51
First of all - thank you for your answer, I really appreciate it. This is interesting - I have re-checked and it takes me 32ms to get the result on my development machine: Server Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny4 with Suhosin-Patch X-Powered-By PHP/5.2.6-1+lenny4 (PHP is installed as mod_php) Still, it is very important for me to be able to postpone processing. If I can't do it on NginX I will probably have to find another server that can do this (overall load on the server is less important than quick response times in this case). I'm really hoping it's just a config thing... :) >From what I understand: - PHP offers no way to prematurely close the connection except by setting and reaching Content-Length - it is the web server (NginX / Apache) that can (should?) close the connection in this case I can't make PHP close the conenction, so my only hope is NginX. Can it be told to do so? Am I missing something? Thanks again! Hoang Hoang Wrote: ------------------------------------------------------- > > > The processing bit cannot be avoided, but the > figure out that all content > > > > function postproc() { > > > 51310 > > -- > Posted via http://www.ruby-forum.com/. > > _______________________________________________ > nginx mailing list > nginx@nginx.org > http://nginx.org/mailman/listinfo/nginx Posted at Nginx Forum: http://forum.nginx.org/read.php?2,51310,51672#msg-51672
on 2010-02-07 18:05
Hi, Not really to change you method on doing things. but you still will encounter slow response times for users eventually since that PHP process is *still* processing things after that user is done and won't be ready for the next user until it is done processing that script. So theoretical if you had 5 max PHP processes to handle client requests and say each PHP script take 500ms to complete but only 100ms is until your Connection: close. If 6 users hit your server at once. That user would have to wait the full 500ms until a free PHP process is available to process his request and then take the additional 100ms for it to see content. So now his experience for the page to load up is it takes almost 600ms. Something i would suggest is using a messaging queue and a "few PHP process's that are just designed to process the queue" this allows you to separate your user processing and your offline processing. Which will also allow you to offload your work to another server if it starts growing and such. here is website with some links to some message queues. http://blog.fedecarg.com/2008/11/03/getting-started-with-message-queues/ v/r, Rob
on 2010-02-07 19:31
Rob, thank you for the idea! We have used it before on other problems, though I had no idea there are libraries made to address this problem (I used my own solution). Thanks for the link, the projects there look very promising. However, the way I see it, this approach is only useful if you want to distribute the load across other machines or across time (so that major work is done when the load is lower). In our case the application runs on several machines already and we can add more if necessary. Also, the work MUST be done at about the time the request was issued, so it cannot wait 10 minutes when the load might be lower. I think in that case the only solution is to compute when we get the requests, with the possible optimization of returning the output before all work is done. Or am I mistaken? When the requests start getting slow (because they are waiting for other requests to finish) we can just add more machines (or enlarge max. number of PHP processes limit first ;) and we're done. So, still searching for the culprit that doesn't close the connection to browser when Content-Length is reached... :) Any ideas? Or is this a FastCGI issue? Is there any other way to use PHP with NginX? Thanks again! Posted at Nginx Forum: http://forum.nginx.org/read.php?2,51310,51782#msg-51782
on 2010-02-07 19:47
> So, still searching for the culprit that doesn't close the connection to browser when Content-Length is reached... :) Any ideas? > > Or is this a FastCGI issue? Is there any other way to use PHP with NginX? I believe this is a FastCGI issue. And nginx buffer's the FastCGI response until FastCGI request is completed. The Header("Connection: close"); is only used to prevent using Keep-alive connection. It tells the browser to terminate the connection and not keep them open, thus having no effect on when the data gets to the client. A suggestion that might work as your needing is stripping your apache down to only using mod_php and anything else you might want. and basically use it as a PHP process manager. Then you can just proxy your requests to apache for the php requests and turn proxy_buffering off http://wiki.nginx.org/NginxHttpProxyModule#proxy_buffering which then *should* produce the results you require. This allow you to use nginx for your static resources while just utilizing apache as just a PHP manager. v/r, Rob
on 2010-02-07 20:48
I was hoping for a different answer - I guess I'll just have to make a few of configurations and test what works best. Thank you for helping out! :) Posted at Nginx Forum: http://forum.nginx.org/read.php?2,51310,51813#msg-51813
on 2010-02-08 10:25
cactus wrote:
> is this a FastCGI issue?
You could try asking on a PHP mailing list, or looking through the PHP
source code, to see if there is a function call that will close the
FastCGI connection, while keeping the process open.
Tobia
on 2010-02-08 12:35
>>From what I understand: > - PHP offers no way to prematurely close the connection except by setting and reaching Content-Length While I havent it used myself so not sure if it works 100% as expected there is such feature if you use php with the FPM patchset/manager - fastcgi_finish_request() http://php-fpm.org/wiki/Features#fastcgi_finish_request.28.29 rr
on 2010-02-14 15:29
Reinis Rozitis Wrote: ------------------------------------------------------- > http://php-fpm.org/wiki/Features#fastcgi_finish_re > quest.28.29 Thanks for the info, this is good news! :) I hope it gets in production soon - will try it out anyway, just out of curiosity, I just need to find some extra time... :) Thanks to all, enjoy! Posted at Nginx Forum: http://forum.nginx.org/read.php?2,51310,54461#msg-54461
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.