PHP fsockopen 異步調用接口在nginx上偶爾實效的情況


private function fsock_asy_do($get){
        $fp = fsockopen("ssl://www.xxx.com", 443, $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            stream_set_blocking($fp,0);//開啟非阻塞模式
            $out = "GET /".$get." HTTP/1.1\r\n";
            $out .= "Host: www.xxxx.com\r\n";
            $out .= "Connection: Close\r\n\r\n";
         
            fwrite($fp, $out);
            /*忽略執行結果
            while (!feof($fp)) {
                echo fgets($fp, 128);
            }*/
            usleep(1000);
            fclose($fp);
        }
    }

在這段代碼里面,調用后忽略執行結果直接返回,可用於php異步執行。

在nginx服務器上有一個比較詭異的情況就是有時候無法調用異步的腳本。

查閱相關資料后,是nginx 499 的問題。

其中解決方案有以下,經過對每一個方案的驗證最終得出結果:

1、NGINX 499

查看 NGINX access log,發現這樣的請求會以 499(Client Closed Request)記錄。確定問題是因為:客戶端主動端口請求連接時,NGINX 不會將該請求代理給上游服務(FastCGI PHP 進程),這個時候 access log 中會以 499 記錄這個請求。

要解決這個問題需要將 NGINX FastCGI 忽略客戶端中斷配置打開:

fastcgi_ignore_client_abort on; 

這樣無論客戶端是否斷開,都會將這個請求代理給上游,並且會記錄上游服務處理后的返回狀態。

2、NGINX 線程原因

將nginx的worker_processes 由之前的auto修改為2(我的是單核服務器)

3、NGINX 499

nginx對499的定義是”client has closed connection”,並且在這些情況下會返回這個狀態碼:

  1. upstream 在收到讀寫事件處理之前時發現連接不可用。
  2. server處理請求未結束,而client提前關閉了連接。
  3. upstream出錯,執行next_upstream時發現連接不可用。

一個不安全的做法是在fclose之前,讓當前的進程先睡眠一段時間;我這里設置為10毫秒,這10毫秒的延遲對我完成整個請求的影響不大,同時我也認為nginx一定能在10毫米內把請求轉到fastcgi去執行。這個時間間隔很難把握,不能保證php一定有執行到。

這種方式並不是真正的異步,只是很取巧的強制關閉連接而不等待服務器端響應。所以在Laruence的那2篇文章中,有2個問題:

  • PHP使用fsock不能叫做異步,只是偽異步。
  • fwrite之后馬上執行fclose,nginx會直接返回499

由於我的代碼上面usleep為1000,初步估計是時間不夠導致沒發出去就close了,所以調整為20000。並進行最后測試。

結果晚點更新。

更新結果:測試2天結果顯示正常,的確是usleep數值過小的問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM