现象
在本机安装了一个 Discuz!X3.4 的论坛,其使用 UCenter 作为统一用户登录,在其应用管理页面,通信情况一直提示为“正在连接”:
原因
关于这个问题,网上绝大多数的说法是 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 条日志的时间,发现第 2 、 3 条与第 1 条间隔差不多 29 秒,我们知道, PHP 默认的超时时间为 30 秒,算上点误差, 29 秒也差不多。因此可以认为这个 499 错误是因为 ucenter 服务器发起了 ping 请求(第 3 行日志),一直没有接收到返回值,结果超时断开连接,从而导致 discuz 服务器出现 499 错误。
整个流程如下图:
知道是 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 的返回值,所以实际上还是通信失败。
不过再进一步分析上面的流程,从 nginx 与 php 的关系来看,发现整个请求处理如下图:
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 进程:
再回到 ucenter 的应用管理页面,刷新,结果如下:
啥情况?我们上面折腾了半天,只是从“正在连接”变成了“通信失败”,问题还是没有解决啊!
不过呢,跟踪代码可以验证, 499 的问题的确是彻底解决了,至于为什么还是“通信失败”,那是另外一个问题了,请参见《 Unable to find the socket transport "http" 》。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 详解nginx的请求限制(连接限制和请求限制)
- angular请求防抖,以及处理第一次请求失效
- RxHttp 一条链发送请求,新一代Http请求神器(一)
- RxHttp 一条链发送请求,新一代Http请求神器(一)
- 利用Jsonp跨域请求数据(原生和Jquery的ajax请求),简单易懂!
- Python网络请求库Requests,妈妈再也不担心我的网络请求了
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
A Project Guide to UX Design
Russ Unger、Carolyn Chandler / New Riders Press / 2009-3-23 / USD 39.99
"If you are a young designer entering or contemplating entering the UX field this is a canonical book. If you are an organization that really needs to start grokking UX this book is also for you. " -......一起来看看 《A Project Guide to UX Design》 这本书的介绍吧!