PHP, Nginx, and Output Flushing

Posted by Justin Carmony on January 24th, 2011

Alright, so one of the few hangups I’ve ran into with moving from Apache to Nginx was output buffering. Now, we have a few administrative tools we use to perform large operations on our library and data. These scripts can take normally 3-5 minutes to run, and they output their progress and what step they are on as they run. The way they do this is after ever step in PHP I issue the same two commands:


[php]

ob_flush(); // Flush anything that might be in the header output buffer

flush(); // Send contents so far to the browser

[/php]


Well, with Nginx, it will wait for an entire response from the PHP-FPM instance before sending data to the browser. This is because traditionally the time to generate the response is less than the time to send the response to the browser, so Nginx will let the CGI instance finish as quick as possible to free it up for other requests. Well, even if I called ob_flush() and flush(), Nginx would wait for the entire response before sending it to the client’s browser. So, for our staff panel, I had to disable this buffering. It took a lot of scouring the web, but I finally figured it out:


Nginx Configuration


You need to set a few variables. I couldn’t actually figure out how to disable the buffer for Nginx, but I could set it very low on a per location configuration.


So I have the following location configurations:


[code]

location ~ .php$ {

include /etc/nginx/fastcgi_params;

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME /path/to/public_html/$fastcgi_script_name;

fastcgi_read_timeout 600;

fastcgi_buffer_size 1k;

fastcgi_buffers 128 1k; # up to 4k + 128 4k

fastcgi_max_temp_file_size 0;

gzip off;

}


[/code]


The important configurations are:


[code]

fastcgi_buffer_size 1k;

fastcgi_buffers 128 1k; # up to 1k + 128 1k

fastcgi_max_temp_file_size 0;

gzip off;

[/code]


So I set the fastcgi_buffer_size and buffers to 1k. Then, you need to set the max temp file size to 0. Nginx by default will start to buffer on the disk. By setting it to 0 it will send it to the browser. The last piece of the puzzle I missed was turning gzip off, because it would try to buffer, even if it exceeded 1k, to compress the response.


Now, to get it to work, in my php script I echo out 1k worth of html commented out text to ensure everything else after it gets sent to the browser.


Now, I don’t recommend these settings for busy productions servers. However, only 3 people use this staff panel, so the performance differences are extremely low.

About Justin Carmony

Justin is the Director of Engineering for Deseret Digital Media, President of the Utah PHP Usergroup, and member of the Utah Open Source Foundation which organizes the OpenWest Conference. Justin loves just about anything with web technologies from PHP, JavaScript, Node.js, Salt, and managing engineering teams.

Learn More