Nginx下,請求本機另外Host很慢

現象

在本機安裝了一個Discuz!X3.4的論壇,其使用UCenter作爲統一用戶登錄,在其應用管理頁面,通信情況一直提示爲“正在連接”:

  image.png

原因

關於這個問題,網上絕大多數的說法是nginx服務器在Windows上有問題,建議更換爲Apache,我更換到Apache下,也確實是問題解決了,但是我還是覺得nginx不至於有這種問題,一定有解決的辦法。

 

再繼續查找,發現nginx日誌裏有報告499錯誤,網上說499錯誤的原因是客戶端主動斷開了與服務器的連接,可是看ucenter的代碼,貌似並沒有斷開連接的操作,倒是看日誌報告的時間,發現一點端倪:

127.0.0.1 - - [18/Jul/2018:22:35:48   +0800] "GET /uc_server/admin.php?m=app&a=ls&…

127.0.0.1 - - [18/Jul/2018:22:36:19   +0800] "GET   /api/uc.php?code=434eRMR%2FD%2FtjZ357V3sA9RLPqp0rpGfi7ryntpyVEEYay3xgen8Oqk9ETjgEXNbyEbKItHYPZqs   HTTP/1.0" 499

127.0.0.1 - - [18/Jul/2018:22:36:19   +0800] "GET /uc_server/admin.php?m=app&a=ping&inajax=1&url=…

 

1行日誌,是ucenter應用管理中心頁面的鏈接,在這個頁面裏,ucenter向本機的Discuz服務器發出通信驗證請求(第3行日誌),而第2行日誌,就是Discuz服務器收到的通信驗證請求,499錯誤就是出現在此行。

 

仔細查看這3條日誌的時間,發現第23條與第1條間隔差不多29秒,我們知道,PHP默認的超時時間爲30秒,算上點誤差,29秒也差不多。因此可以認爲這個499錯誤是因爲ucenter服務器發起了ping請求(第3行日誌),一直沒有接收到返回值,結果超時斷開連接,從而導致discuz服務器出現499錯誤。

 

整個流程如下圖:

image.png

知道是499錯誤,於是又查找如何解決499問題,結果大多數提出要在nginx服務器中添加如下配置:

proxy_ignore_client_abort  on;

fastcgi_ignore_client_abort on;

 

Discuz的配置項中添加了上述配置:

location ~ \.php$ {

            root         C:/PHPackage/workspace/github/DiscuzX/bbs;

            fastcgi_pass   127.0.0.1:9090;

            fastcgi_index  index.php;

            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

            include        fastcgi_params;

            proxy_ignore_client_abort  on;

            fastcgi_ignore_client_abort on;

          }

 

再運行服務器,發現499問題果然沒了,但是通信問題依然沒有解決,只是日誌變爲如下了:

127.0.0.1 - - [18/Jul/2018:22:35:48   +0800] "GET /uc_server/admin.php?m=app&a=ls&…

127.0.0.1 - - [18/Jul/2018:22:36:19   +0800] "GET   /api/uc.php?code=434eRMR%2FD%2FtjZ357V3sA9RLPqp0rpGfi7ryntpyVEEYay3xgen8Oqk9ETjgEXNbyEbKItHYPZqs   HTTP/1.0" 200

127.0.0.1 - - [18/Jul/2018:22:36:19   +0800] "GET /uc_server/admin.php?m=app&a=ping&inajax=1&url=…

 

配置生效了,但是有個毛用啊,通信還是不成功。第1條日誌和下面兩條日誌還是差了差不多30秒左右。回過頭來仔細分析上面的兩個配置項,應該是讓nginx服務器忽略客戶端斷開的錯誤,注意,僅僅是讓服務器忽略這個錯誤,也就是說,當ucenter請求超時,斷開連接的時候,discuz服務器忽略了這個錯誤,從而返回200,可是ucenter實際上已經斷開了,也收不到discuz的返回值,所以實際上還是通信失敗。

 

不過再進一步分析上面的流程,從nginxphp的關係來看,發現整個請求處理如下圖:

image.png

 

nginx收到請求後,發現是需要執行PHP代碼,於是將請求就轉給了PHP-CGI進程,由該進程找到PHP代碼並執行,但是在PHP代碼中,又再次向本機的另一個服務器發出HTTP請求,nginx收到後,發現同樣要執行PHP代碼,於是將請求又轉回給PHP-CGI進程,但是系統中PHP-CGI進程只開了一個,後面的PHP代碼要等到上面的執行完畢才能執行,而後面的PHP代碼卻又是上面的代碼請求產生的,於是就阻塞了。

 

1.1.3  解決

分析至此,解決的思路就已經很清晰了,既然一個PHP-CGI線程處理不過來,那麼就增加一個線程好了,修改啓動nginx服務器的批處理代碼如下,僅修改一個數字,見紅色字體部分:

@echo off

REM Windows 下無效

REM set PHP_FCGI_CHILDREN=5

 

REM 每個進程處理的最大請求數,或設置爲 Windows 環境變量

set PHP_FCGI_MAX_REQUESTS=1000

 

echo Starting PHP FastCGI...

rem RunHiddenConsole   C:/PHPackage/PHP/php-cgi.exe -b 127.0.0.1:9090 -c C:/PHPackage/PHP/php.ini

RunHiddenConsole xxfpm   "C:/PHPackage/PHP/php-cgi.exe -c C:/PHPackage/PHP/php.ini" -n 2 -i 127.0.0.1 -p 9090

 

echo Starting nginx...

RunHiddenConsole   C:/PHPackage/nginx-1.15.1/nginx.exe -p C:/PHPackage/nginx-1.15.1

 

該數字原來是1,現在改爲2,重新啓動服務器,看任務管理器,果然有兩個PHP-CGI進程:

image.png

 

再回到ucenter的應用管理頁面,刷新,結果如下:

image.png

 

啥情況?我們上面折騰了半天,只是從“正在連接”變成了“通信失敗”,問題還是沒有解決啊!

不過呢,跟蹤代碼可以驗證,499的問題的確是徹底解決了,至於爲什麼還是“通信失敗”,那是另外一個問題了,請參見《Unable to find the socket transport "http"》。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章