nginx和php-fpm连接超时的那点事

现在线上系统的架构大致是这样的,除去cache的proxy机器外,还有项目的nginx proxy机器,后面跟nginx webserver + php-fpm。有时候,会看到proxy nginx的日志里面会有各种异常状态码,比如499,502,504等,这些是什么情况导致的呢?最近一一测试了下。

架构示意

 nginx proxy => nginx webserver => php-fpm

状态码说明

499:客户端(或者proxy)主动断开连接
502:网关错误(Bad Gateway)
504:网关超时:(Gateway Timeout)

1 proxy和webserver不能连接

1.1 proxy_pass ip不存在

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

1.2 proxy_pass ip存在

1)webserver机器上端口上没有对应服务。

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

2)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返回的状态码。

3) 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=60
webserver的nginx.conf中fastcgi_read_timeout=300
php-fpm中的 request_terminate_timeout=120

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 如下:

<?php
sleep(7);
echo "haha\n";
ob_flush();
flush();
sleep(7);
echo "haha after 7s\n";
?>

这整个请求的响应时间是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,从而超时。

在如上面配置好后,可以发现,浏览器输出了haha\nhaha 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 -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 96537
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1000000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 96537
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

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

另外,系统允许打开的最大文件数在配置file-max中。

# cat /proc/sys/fs/file-max
2471221

要修改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 files
bob        hard nofile 4096
## Example soft limit for max opened files
bob        soft nofile 1024

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

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • 1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单...
    rosekissyou阅读 10,170评论 5 124
  • Nginx简介 解决基于进程模型产生的C10K问题,请求时即使无状态连接如web服务都无法达到并发响应量级一万的现...
    魏镇坪阅读 1,980评论 0 9
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 上一篇《WEB请求处理一:浏览器请求发起处理》,我们讲述了浏览器端请求发起过程,通过DNS域名解析服务器IP,并建...
    七寸知架构阅读 80,860评论 21 356
  • 《老男孩Linux运维》笔记 隐藏Nginx软件版本号 一般来说,软件的漏洞都和版本有关。因此要尽量隐藏对访问用户...
    Zhang21阅读 3,600评论 0 28