DevOps: 一例高负载多并发服务器链接池满的异常排解过程

今天是三八国际妇女节, 也是中国农历二月二/龙抬头的节日,恭祝女同胞节日快乐!恭祝中国善良的人们都抬头见喜!缓存

好一阵子没更新Blog,今天也借这喜气冲刷一下往日的阴霾,通过多日的观察,终于找到这阵子“有福新闻”高负载多并发服务器的异常报错背后的缘由之一。此前在Blog中频繁观测到 GWA2 PHP Memcached的报错,而且在代码层面进行了屡次调优,问题暂时获得缓解,深层并未深究出个因此然。服务器

“GWA2 PHP Memcached自动追加服务器链接?一例缓存服务被击穿的异常分析”, -R/52SP  。网络

在进行平常服务器状态巡检时,先是发现 Apache 在很多天的持续运行中,会有 segmentation fault 致使的死掉,因而对 Apache 2.4.x 进行升级到最新版的操做,然而加了保护措施。尽管偶尔有 Apache child 有 segmentation fault退出,但整个服务顽强的活着.并发

后续几日的连续观测中,Apache暂无异常死掉,而 GWA2 PHP Memcached再次开始报错,报错信息为惟一的 127.0.0.1/11211 服务被标记为 DEAD (error code: 35). 然而在终端用 telnet 进行手工模拟时,memcached的服务又是正常的,这是为什么?时好时坏,随机出错吗?app

近日继续探测,在最近的一次服务器上尝试使用 ping ufqi.com 时,命令行开始报错说 sendmeg not permitted… 因而一例服务器操做系统层面的问题被曝露出来。ide

ping命令的没法执行,多是网络配置或操做系统异常,循着这个思路,咱们使用 journalctl -f 命令,很快看到 kernel层的报错信息:memcached

Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet
Mar 08 04:43:06 srv21 kernel: nf_conntrack: nf_conntrack: table full, dropping packet优化

原来是系统的网络链接池出现了问题!关于 “nf_conntrack: table full, dropping packet” 这里 -R/u2SR 有详细的解释。 简单地说,操做系统集成了 Netfilter 防火墙服务,基于 iptables 的操做系统的链接管理器中,有四个 table(表) 和五个 chain(链)。操作系统


Fig1. Iptables 4 tables and 5 chains.net

Tables: categorized by different operations to data packets.

raw: highest priority, only appied to PREROUTING and OUTPUT chain. When we don’t need to do NAT, we can use RAW table to increase performance.

mangle: modify certain data packet

nat: NAT, port mapping, address mapping

filter: filter

Chains: categorized by different hooks.

PREROUTING: packet before going to route table

INPUT: after packet passing route table, destination is current machine

FORWARDING: after packet passing route table, destination is not current machine

OUTPUT: packet comes from current machine and to outside

POSTROUTIONG: packet before going to network interface

当操做系统处理 TCP/IP 链接相关模块出错时,全部基于链接的服务都会报出异常。这是此前在代码层不管如何优化都没办法解决OSI分层中更底层的问题。

操做系统默认的并发链接数为 65535, 经过命令:cat /proc/sys/net/netfilter/nf_conntrack_max  能够查看到。 若是经过命令 cat /proc/sys/net/netfilter/nf_conntrack_count 得到到的数字等于 max 的最大值时,此时再有新建立链接的需求就会报错,当建立链接失败时,基于其上的全部应用都将失败,而这些在代码层并不容易解决。推荐的 /proc/sys/net/netfilter/nf_conntrack_max 值的计算公式: CONNTRACK_MAX = RAMSIZE (in bytes) / 16384 / (ARCH / 32) , 如 8GB RAM in x86_64 OS,  max = 8*1024^3/16384/2=262144 。

当一台繁忙的服务器的链接数超过默认值时,须要经过修改 /proc/sys/net/netfilter/nf_conntrack_max  来使得系统可以接收更多链接进来。

临时修改:
echo 524288 > /proc/sys/net/netfilter/nf_conntrack_max
or
sysctl -w net.netfilter.nf_conntrack_max=262144
永久修改:
在 /etc/rc.d/after.local  或者 /etc/rc.d/rc.local 中增长上述命令行语句。

除了增长 /proc/sys/net/netfilter/nf_conntrack_max 参数设定外,还能够经过调整 iptables 的表或者链上相关规则来进行调优,更多参考: -R/u2SR 。

“有福新闻”, “全国招投标信息中心” 等服务又能够畅快地运行并有信心地迎接下一次洪峰的到来。

小结:
1. 在代码层很难发现操做系统层的问题,可行的路线是分析应用层源码;
2. 系统层的异常,经过具备随机性,好比链接数,是一个动态变化数据,可能下一秒异常就没有了,没法肯定重现的问题为 troubleshooting 带来了必定的障碍。
可是,已有的问题,在没解决以前,会再次发生,这是肯定的。

-R/n2SO 

相关文章
相关标签/搜索