在實際項目中常常會有這樣的需求,對於前端發過來的請求,須要在後端進行長時間的處理,但爲了讓使用者有更好的體驗,爲了讓PHP在後端處理長時間任務時不阻塞,快速響應頁面請求,所以在這裏對fastcgi_finish_request的應用進行總結概括。固然php實現非阻塞的方式有不少種,好比異步腳本、swoole,但我的認爲fastcgi_finish_request最爲簡單方便。php
(PHP 5 >= 5.3.3, PHP 7)html
fastcgi_finish_request — 沖刷(flush)全部響應的數據給客戶端前端
boolean fastcgi_finish_request ( void )
此函數沖刷(flush)全部響應的數據給客戶端並結束請求。 這使得客戶端結束鏈接後,須要大量時間運行的任務可以繼續運行。後端
成功時返回 TRUE, 或者在失敗時返回 FALSE服務器
echo "program start..."; file_put_contents('/tmp/garylog.log','start-time:'.date('Y-m-d H:i:s')."\n", FILE_APPEND); fastcgi_finish_request();sleep(1); // set_time_limit(0); // sleep(150); $num = 25; $num += 1; sleep(5); echo 'debug...'; file_put_contents('/tmp/garylog.log', 'start-proceed:'.$num.',時間'.date('Y-m-d H:i:s')."\n", FILE_APPEND); sleep(10); file_put_contents('/tmp/garylog.log', 'end-time:'.date('Y-m-d H:i:s')."\n", FILE_APPEND);
運行測試
swoole
從代碼的可移植性講的話, 能夠在代碼中附上以下代碼:併發
if (!function_exists("fastcgi_finish_request")) { function fastcgi_finish_request() { } }
不會形成代碼部署在非fpm環境下形成問題.異步
對於上面說到的問題:在高併發下執行時間太久也會致使fastcgi進程不夠用,不能及時釋放。同時咱們的需求僅僅是爲了起到觸發的做用,並不須要每次運行,那麼能夠考慮使用下面的方法,避免重複佔用進程。函數
$processId = realpath(__FILE__) . '-' . get_class($this); $filename = md5($processId); $file = '/tmp/'.$filename; if(!file_exists($filename)){ file_put_contents($file, getmypid()); }else{ return true; } ## do somthing 須要長時間處理的代碼 //處理完成後刪除進程id記錄文件 unlink($file);