架构示意

nginx proxy => nginx webserver => php-fpm

状态码解释

499:客户端(或者proxy)主动断开连jie502:网关缺点(Bad Gateway)504:网关超时:(Gateway Timeout)1 proxy和webserver不能连接

1.1 proxy_pass ip不存在:

php连接超时nginx和phpfpm衔接超时之解决办法 Bootstrap

这时候会重复发送arp解析协议,约3秒后超时,proxy返回码为502。

1.2 proxy_pass ip存在:

webserver机器上端口上没有对应做事;

webserver所在机器的内核会直接返回RESET包,没有额外超时,proxy返回码为502。

webserver机器端口上有做事,但是iptables DROP了proxy的包;

由于webserver drop(iptables -I INPUT -s xxx.xxx.xxx.xxx -j DROP)了proxy的包,proxy会TCP连接不断重试,默认会重试60秒后proxy返回码504,这个重试韶光60秒由参数proxy_connect_timeout指定,重试间隔便是TCP的重试间隔(1,2,4...)。

如果在超时之前,客户端主动关闭连接(比如停滞浏览器的要求),这个时候proxy会记录 499状态码,而且$request_time 记录的是proxy已经处理的韶光,而$upstream_response_time为-。
客户端主动关闭后,proxy也不会再向webserver发送重试要求。

但是如果你在proxy配置了proxy_ignore_client_abort on,那么即便客户端主动关闭,proxy还是会一直的发送重试要求到webserver,直至超时,记录的状态码为webserver返回的状态码。

webserver机器端口有做事,但是iptables reject了proxy的包。

由于webserver reject(iptables -I INPUT -s xxx.xxx.xxx.xxx -j REJECT)了proxy的包,与drop不同之处在于,这个时候webserver会返回一个端口不可达的ICMP包给proxy,proxy会重试一次后返回 502 给客户端,超时时间约为1秒。

2 proxy和webserver连接正常(要求韶光过长)

proxy的nginx.conf中的proxy_read_timeout=60webserver的nginx.conf中fastcgi_read_timeout=300php-fpm中的 request_terminate_timeout=120

nginx.conf配置文件

2.1 php实行韶光超过proxy的proxy_read_timeout:

假设php-fpm有一个test.php实行韶光为100秒,超过了默认的proxy_read_timeout=60,则到1分钟后proxy会关闭到webserver的连接,webserver记录的返回码为499,proxy的返回码为 504,客户端看到的返回码也便是 504。

关于proxy_read_timeout要多说一句,在nginx文档中可以看到这个参数的含义是:

The timeout is set only between two successive read operations,not for the transmission of the whole response.

意思是说并非response的传输超时,而是两次读操作之间的间隔超时。
比如在proxy中设置proxy_read_timeout=10,而测试的test.php 如下:

<?phpsleep(7);echo \公众haha\"大众;ob_flush();flush();sleep(7);echo \公众haha after 7s\"大众;?>

这全体要求的相应韶光是14秒,实在是不会超时的,由于相邻两次读操作的间隔是7秒小于10秒。
把稳代码中的ob_flush()和flush()两个函数,个中ob_flush()是为了刷php的缓存,flush()则是为了刷系统层面的缓存。
将/etc/php5/fpm/php.ini中设置output_buffering=off,则可以不用调用ob_flush()了,但是flush()还是须要的。
如果不flush的话,php会等到全体相应完成才会将数据返回给webserver,webserver再返回给proxy,在没有返回全体相应之前(14秒才能返回),超过了 proxy_read_timeout的10秒,此时,proxy会关闭和webserver的连接,导致涌现504缺点。
为了这个测试test.php不超时,webserver的nginx还要加一个配置fastcgi_buffering off,由于虽然我们的php返回了数据了,但是webserver的nginx还是缓存了fastcgi的返回,导致没有及时将数据返回给proxy,从而超时。

php.ini文件

在如上面配置好后,可以创造,浏览器输出了hahahaha after 7s那么问题来了,这两个字符串是同时输出的,并没有像代码中那样隔了7秒,那这个问题是什么导致的呢?答案是proxy的nginx也有缓存配置,须要关闭才能看到先后输出两个字符串的效果。
nginx proxy的缓存配置为proxy_buffering off,这样你就能看到先后输出两个字符串的效果了。

2.2 php实行韶光超过webserver的fastcgi_read_timeout:

设置fastcgi_read_timeout=10,test.php实行韶光100秒,则10秒后webserver会关闭和PHP的连接,webserver记录日志的返回码为 504,proxy日志的返回码也是 504。

2.3 php实行韶光超过php-fpm的request_terminate_timeout:

设置request_terminate_timeout=5,test.php还是实行100秒,可以创造5秒之后,php-fpm会终止对应的php子进程,webserver日志的状态码为 404,proxy的日志的状态码也是 404。

注:经测试,在php-fpm模式中,php.ini中的max_execution_time参数没有什么效果。

3 关于文件数问题

Linux里面的一些限定参数可以通过ulimit -a查看,比如我的debian8.2系统的输出如下:

# ulimit -acore file size (blocks, -c) 0data seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (-i) 96537max locked memory (kbytes, -l) 64max memory size (kbytes, -m) unlimitedopen files (-n) 1000000pipe size (512 bytes, -p) 8POSIX message queues (bytes, -q) 819200real-time priority (-r) 0stack size (kbytes, -s) 8192cpu time (seconds, -t) unlimitedmax user processes (-u) 96537virtual memory (kbytes, -v) unlimitedfile locks (-x) unlimited

个中open files是一个进程可以同时打开的文件数,超过则会报too many open files缺点,修正可以通过ulimit -n xxx来实现。
而max user processes则是用户最多创建的进程数。

其余,系统许可打开的最大文件数在配置file-max中。

# cat /proc/sys/fs/file-max2471221

修正file-max可以通过# sysctl -w fs.file-max=1000000修正,永久生效须要在/etc/sysctl.conf中加入这行fs.file-max=1000000然后sysctl -p即可。

要针对用户限定文件数之类的,可以修正/etc/security/limits.conf,内容格式如下:

<domain> <type> <item> <value>## 比如限定 bob这个用户的一个进程同时打开的文件数## Example hard limit for max opened filesbob hard nofile 4096## Example soft limit for max opened filesbob soft nofile 1024

nginx配置中的worker_rlimit_nofile可以配置为open files这个值。

ulimit -a命令

sysctl.conf文件