使用fastcgi_finish_request 處理耗時的任務
阿新 • • 發佈:2019-01-12
我們業務中經常遇到這樣的場景:比如生成檔案較大的excel ,非常耗時,有可能需要5到30妙的時間,甚至更長導致瀏覽器連線超時。
另外一個就是體驗問題,使用者需要長時間的等待響應的完畢,體驗較差。
類似的場景還有
1:需要處理大的檔案
2:傳送郵件或簡訊,尤其是需要迴圈傳送郵件通知等
3:呼叫遠端耗時的api 等
遇到這種情況,如果您的伺服器使用的也是nginx ,那麼可以考慮使用下面的函式
fastcgi_finish_request();
該函式的作用:
理解發送響應給瀏覽器,這樣使用者的等待時間很短,但是php程序其實還在伺服器中執行。
這樣就達到了兩個目錄目的,有點類似於非同步任務
- 響應快:比如傳送郵件需要3秒時間,但使用者無感知,1妙之內就告訴使用者傳送郵件完畢
- 耗時任務後臺執行:瀏覽器響應結束了,使用者可以做其他的事情。後臺程序默默的執行傳送郵件等任務
舉例效果圖:
1:該程式模擬一個耗時的任務,需要5妙才能執行完畢
經過上面的演示,我們達到了目的
1:很快的響應,1毫米之內,瀏覽器響應結束
2:後臺任務,注意右側上方的日誌,每秒輸出一個時間戳
全部測試程式碼如下
<?php /** * 設定超時時間,變成不限制 * */ set_time_limit(0); /** * 本函式模擬非常耗時的任務,執行完畢需要5秒的時間 */ function writeFile() { $path = '/home/ndw/test/1.txt'; file_put_contents($path,'程式執行開始' . PHP_EOL,FILE_APPEND); for($i =0;$i < 5;$i++) { file_put_contents($path,time() . PHP_EOL,FILE_APPEND); sleep(1); } file_put_contents($path,'程式執行結束' . PHP_EOL,FILE_APPEND); } /** * 輸出文字標記,任務開始 */ echo('任務開始'); /** * 後臺執行非常耗時的任務 */ register_shutdown_function(writeFile); /** * 立即傳送請求 */ fastcgi_finish_request();
備註:
- 主角是fastcgi_finish_request,其實把要執行的程式碼放到該函式的後面,就可以了。
- register_shutdown_function函式,具體百度,這個函式主要是為了考慮修改成本,有的程式已經成型,不方便作大的調整,可以把函式提前註冊,這樣他是不會立即執行的。頁面響應完畢後,再呼叫本函式
- 建議不要濫用,適合一些耗時但流程簡單的任務(比如傳送郵件)。因為是後臺執行,如果程式出錯,前臺是看不到的,需要有日誌記錄和重試機制。