我有一个假设:有时 TCP 连接到达的速度比我的服务器更快accept()
。他们排队直到队列溢出,然后就会出现问题。
我如何确认这种情况正在发生?
我可以监控接受队列的长度或溢出数量吗?柜台是否暴露在外?
答案1
要检查队列是否溢出,请使用 netstat 或 nstat
[centos ~]$ nstat -az | grep -i listen
TcpExtListenOverflows 3518352 0.0
TcpExtListenDrops 3518388 0.0
TcpExtTCPFastOpenListenOverflow 0 0.0
[centos ~]$ netstat -s | grep -i LISTEN
3518352 times the listen queue of a socket overflowed
3518388 SYNs to LISTEN sockets dropped
参考: https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/
要监视队列大小,请使用 ss 命令并查找 SYN-RECV 套接字。
$ ss -n state syn-recv sport = :80 | wc -l
119
参考: https://blog.cloudflare.com/syn-packet-handling-in-the-wild/
答案2
系统挖掘将在每个系统调用结束时提供一些此类信息accept
作为queuelen
参数。它还将队列的长度显示为queuemax
。
7598971 21:05:30.322229280 1 gunicorn (6451) < accept fd=13(<4t>127.0.0.1:45882->127.0.0.1:8003) tuple=127.0.0.1:45882->127.0.0.1:8003 queuepct=0 queuelen=0 queuemax=10
据我所知,它没有提供任何机制来准确了解队列何时或多少次溢出。将其与定期监控或类似的监控整合起来会很麻烦collectd
。
答案3
您正在寻找的是命令输出中的条目,sysctl -a
如下所示:
net.ipv4.tcp_max_syn_backlog = 4096
在上面的示例中,SYN 状态连接的积压最多为 4096。您可以根据服务器中的 RAM 数量来增加该数量。我认为 32K 的待办事项是调整重负载 Web 服务器的良好开端。
另请确保以下各项未设置为 1:
net.ipv4.tcp_abort_on_overflow = 0
否则如果积压溢出肯定会丢包。
sysctl -a | grep backlog
您可以使用或轻松检查值sysctl -a | grep overflow
。
此外,您可以在下面找到“已删除”标签
ifconfig -a
命令的输出。这显示了每个接口丢弃了多少数据包以及其他数据和错误等。
对于记录丢弃的数据包,有一篇针对 RHEL 7 的 [付费] 文章:https://access.redhat.com/solutions/1191593
如需进一步研究,您可以阅读http://veithen.io/2014/01/01/how-tcp-backlog-works-in-linux.html
根据史蒂文的书《TCP/IP 插图》,它在这里指出:
队列限制适用于 [...] 不完整连接队列上的条目数 [...] 和 [...] 已完成连接队列上的条目数 [...]。”
它还指出:
已完成的连接队列几乎总是空的,因为当将条目放入此队列时,服务器对accept的调用返回,并且服务器将已完成的连接从队列中取出。
因此,接受队列可能看起来完全是空的,您必须调整 Web 服务器以更快地接受放置在“总聚合”队列上的连接。