You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Much like keepalive_requests for client connections, this is mostly
a safeguard to make sure connections are closed periodically and the
memory allocated from the connection pool is freed.
Nginx
keepalive_requests
踩坑总结问题起因
Waf
(基于 Nginx 实现的七层防护系统)上线上后,QA 同事对系统进行大流量压测(十万级 QPS),发现部署机器处于TIME_WAIT
状态的 TCP 连接数异常,高峰期达到几千。按理 waf 这边使用的是长连接,连接数不应该这么多的。问题定位
首先确认下 TCP 连接处于 TIME_WAIT 原因:
这就说明确实是服务端这边主动关闭了连接。我重新 review 了一下 Nginx 配置,确实使用了长连接,并且,我上线前在本地使用 ab 工具压测过, 没有观察到连接数量异常情况。
只能祭出 google 大法了,发现可能是 keepalive_requests 设置太小引起的。
而我并没有配置
keepalive_requests
,所以,就是使用的默认数 100,即一个长连接只能处理一百个请求,然后 Nginx 就就会主动关闭连接,使大量连接处于TIME_WAIT
状态。我猜测很大可能就是这个原因了,为了在本地验证,我将
keepalive_requests
分别设为10
,50
,100
,1000
,分四组分别进行压测,对比结果。压测命令:
然后使用
netstat -nat |awk '{print $6}'|sort|uniq -c
查看连接数,结果出乎意料的清晰,TIME_WAIT
数量基本等于 总请求数/keepalive_requests,这就基本证实了猜测。问题解决
其实大部分情况下,使用默认值是没有问题的,但是对于 QPS 较大的情况,默认数值就不够了,综合考虑,在 Nginx conf 增加配置项:
可能很多人更习惯不做限制,可以设置一个最大的数来实现这个效果 --
2^32 - 1 = 4294967295
(这是在运行32位和64位系统的计算机中是无符号长整形数所能表示的最大值,亦是运行32位系统的计算机中所能表示的最大自然数),疑问
虽然问题解决了,但是,为什么 Nginx 要对单个长连接的处理请求数进行最大限制呢?一般我们理解的,长连接是在连接池里维护的,只要连接本身没有超时等异常问题,是可以一直复用的。
关于这个疑问,讨论的似乎不多,只在 Nginx 开发者论坛上看[nginx] Upstream keepalive: keepalive_requests directive.有所讨论,开发者有模糊的表述:
但是,为什么需要定时关闭连接,释放内存?难道这只是一种保护策略,怕极端情况下,用户配置不当,导致连接一直不断开,引起内存问题?很奇怪,从 Nginx 开发日志也没有找到特别说明。
另外,上面的讨论贴其实是讨论 Upstream keepalive_requests 设置的,最新版 Nginx (version 1.15.3.) 在 Upstream 内增加了
keepalive_requests
配置项,与keepalive_requests client connections
类似,默认值也是 100。也就是说,之前的版本,连接上游的连接是没有次数限制的,完全由上游的服务端的keepalive_requests
设置,但是,如果上游服务端不使用 Nginx 的话,别的系统一般也是没有这个限制的。在大流量的场景下,Nginx 代理升级到这个版本,就可能会引起连接异常情况。关于默认值和兼容性,作者的回复也比较主观,可能这块确实很难面面俱到吧,只能满足大多数场景了。
综上,在 QPS 较高的场景下,服务端要注意将 keepalive_requests 设置的大一些,如果 Nginx 升级到最新版,还需要注意设置 upstream 的keepalive_requests,这两个数量可以不一致,一般服务端要设置的大些,因为一般来说,一个服务端可能对应多个代理。
The text was updated successfully, but these errors were encountered: