在本机安装了一个Discuz!X3.4的论坛,其使用UCenter做为统一用户登陆,在其应用管理页面,通讯状况一直提示为“正在链接”:php
关于这个问题,网上绝大多数的说法是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" 499 …ajax 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条日志的时间,发现第2、3条与第1条间隔差很少29秒,咱们知道,PHP默认的超时时间为30秒,算上点偏差,29秒也差很少。所以能够认为这个499错误是由于ucenter服务器发起了ping请求(第3行日志),一直没有接收到返回值,结果超时断开链接,从而致使discuz服务器出现499错误。app
整个流程以下图:socket
知道是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的返回值,因此实际上仍是通讯失败。
不过再进一步分析上面的流程,从nginx与php的关系来看,发现整个请求处理以下图:
nginx收到请求后,发现是须要执行PHP代码,因而将请求就转给了PHP-CGI进程,由该进程找到PHP代码并执行,可是在PHP代码中,又再次向本机的另外一个服务器发出HTTP请求,nginx收到后,发现一样要执行PHP代码,因而将请求又转回给PHP-CGI进程,可是系统中PHP-CGI进程只开了一个,后面的PHP代码要等到上面的执行完毕才能执行,然后面的PHP代码却又是上面的代码请求产生的,因而就阻塞了。
分析至此,解决的思路就已经很清晰了,既然一个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进程:
再回到ucenter的应用管理页面,刷新,结果以下:
啥状况?咱们上面折腾了半天,只是从“正在链接”变成了“通讯失败”,问题仍是没有解决啊!
不过呢,跟踪代码能够验证,499的问题的确是完全解决了,至于为何仍是“通讯失败”,那是另一个问题了,请参见《Unable to find the socket transport "http"》。