在上一篇,小編說到php異步請求,其中fsockopen會有一個缺點,那就是會出現請求丟失的情況,查看 nginx access log,發現這樣的請求會以 499
(Client Closed Request)記錄。
爲什麼?
nginx對499的定義是”client has closed connection”,並且在這些情況下會返回這個狀態碼:
- upstream 在收到讀寫事件處理之前時發現連接不可用。
- server處理請求未結束,而client提前關閉了連接。
- upstream出錯,執行next_upstream時發現連接不可用。
而我們問題是因爲 fwrite之後馬上執行fclose,nginx會直接返回499,客戶端主動端口請求連接時,nginx不會將該請求代理給上游服務(FastCGI PHP 進程),這個時候 access log 中會以 499 記錄這個請求。
要解決這個問題需要將 nginx FastCGI 忽略客戶端中斷配置打開:
fastcgi_ignore_client_abort on;
這樣無論客戶端是否斷開,都會將這個請求代理給上游,並且會記錄上游服務處理後的返回狀態。
當然也可以在腳本頭部中添加以下配置
ignore_user_abort (true);
你也可以這樣?
一個不安全的做法是在fclose之前,讓當前的進程先睡眠一段時間;使用usleep函數設置爲10毫秒,這10毫秒的延遲對整個請求的影響不大,但是我也認爲nginx不一定能在10毫秒內把請求轉到fastcgi去執行。這個時間間隔很難把握,不能保證php一定有執行到。當然你也可以調整時間更長一些,但是這樣我覺得異步就沒必要了。