生产环境的Tomcat在Full GC时,部分客户端请求会有connect timeout报错,然而我们客户端设置的连接超时是10s,FullGC最长不过2s,一番搜索后发现是backlog的锅,在此记录一下backlog的工作原理
How TCP backlog works in Linux
两个队列管理backlog
SYN queue
管理三次握手过程中的连接,使用如下参数控制长度,系统级别/proc/sys/net/ipv4/tcp_max_syn_backlog
accept queue
管理ESTABLISHED状态的连接,这个Q中的连接可以被accpet(2)
处理,Q长度在listen(2)
调用时传入,同时最大值受如下参数限制,应用级别net.core.somaxconn
查看accept queue大小
ss -lt
(查询结果的Send-Q
列)如果accept queue空间耗尽
服务器默认会忽略三次握手最后的ACK
包,可以通过将如下参数设置为1
将忽略变为发送RST
包net.ipv4.tcp_abort_on_overflow
此时服务器仍然处于
SYN RECEIVED
状态,而客户端已经是ESTABLISHED
状态
服务器会继续向客户端发送SYN/ACK
包,重试间隔从3s
开始,重试次数由如下参数控制net.ipv4.tcp_synack_retries = 5
当客户端收到重发的
SYN/ACK
包,会重发ACK
包,如果queue有空间,即进入ESTABLISHED
状态,反之服务端继续忽略ACK
包
当重试次数耗尽,queue仍然没有空间,服务器会发送RST
包,终止连接从客户端角度来看,发送
ACK
后连接已经建立,此时客户端如果发送数据,会导致数据重传,由于TCP Slow-start,重传的数据量会受到限制,如果客户端等待服务器发送数据,即会出现half-open connection问题SYN queue限流
accept queue空间耗尽时,系统会对SYN queue进行限流,即使SYN queue没满,部分SYN
包仍然会被丢弃,由客户端负责重试net.ipv4.tcp_syn_retries = 5
可以通过
netstat -s
查看丢弃的包960 times the listen queue of a socket overflowed
960 SYNs to LISTEN sockets ignored或者
nstat -a
TcpExtListenOverflows 960
TcpExtListenDrops 960分为两个队列的优势
应用根据处理能力管理accept queue的大小
系统管理员根据流量特征管理SYN queue的大小合理设置accept queue大小
设置过大会导致请求堆积,使请求响应变慢
设置过小会导致并发高时部分请求被丢弃,引发不合理的connect timeout错误
|
|
Tomcat
The HTTP ConnectoracceptCount
控制accept queue长度,默认值为100
maxThreads
最大处理线程数,默认值为200
maxConnections
最大连接数,NIO下默认值为10000
,BIO(8.5版本废弃)下同maxThreads
Tuning Tomcat For A High Throughput, Fail Fast System
计算实际处理能力,当超出处理能力时尽量fail fast,防止影响全局性能