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

現象

在本機安裝了一個Discuz!X3.4的論壇,其使用UCenter做爲統一用戶登陸,在其應用管理頁面,通訊狀況一直提示爲「正在鏈接」:php

  image.png

緣由

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

 

再繼續查找,發現nginx日誌裏有報告499錯誤,網上說499錯誤的緣由是客戶端主動斷開了與服務器的鏈接,但是看ucenter的代碼,貌似並無斷開鏈接的操做,卻是看日誌報告的時間,發現一點端倪:git

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

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

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

 

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

 

仔細查看這3條日誌的時間,發現第23條與第1條間隔差很少29秒,咱們知道,PHP默認的超時時間爲30秒,算上點偏差,29秒也差很少。所以能夠認爲這個499錯誤是由於ucenter服務器發起了ping請求(第3行日誌),一直沒有接收到返回值,結果超時斷開鏈接,從而致使discuz服務器出現499錯誤。app

 

整個流程以下圖:socket

image.png

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

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"》。

相關文章
相關標籤/搜索