生产环境的Tomcat在Full GC时,部分客户端请求会有connect timeout报错,然而我们客户端设置的连接超时是10s,FullGC最长不过2s,一番搜索后发现是backlog的锅,在此记录一下backlog的工作原理
How TCP backlog works in Linux
How TCP backlog works in Linux
TCP(7)
两个队列管理backlog
查看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错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 0.000 127.0.0.1 -> 127.0.0.1 TCP 74 53302 > 9999 [SYN] Seq=0 Len=0 0.000 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 0.000 127.0.0.1 -> 127.0.0.1 TCP 66 53302 > 9999 [ACK] Seq=1 Ack=1 Len=0 0.000 127.0.0.1 -> 127.0.0.1 TCP 71 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 0.207 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 0.623 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 1.199 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 1.199 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 6#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0 1.455 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 3.123 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 3.399 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 3.399 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 10#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0 6.459 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 7.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 7.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 13#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0 13.131 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 15.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 15.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 16#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0 26.491 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 31.599 127.0.0.1 -> 127.0.0.1 TCP 74 9999 > 53302 [SYN, ACK] Seq=0 Ack=1 Len=0 31.599 127.0.0.1 -> 127.0.0.1 TCP 66 [TCP Dup ACK 19#1] 53302 > 9999 [ACK] Seq=6 Ack=1 Len=0 53.179 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 106.491 127.0.0.1 -> 127.0.0.1 TCP 71 [TCP Retransmission] 53302 > 9999 [PSH, ACK] Seq=1 Ack=1 Len=5 106.491 127.0.0.1 -> 127.0.0.1 TCP 54 9999 > 53302 [RST] Seq=1 Len=0
|
Tomcat
The HTTP Connector
acceptCount 控制accept queue长度,默认值为100
maxThreads 最大处理线程数,默认值为200
maxConnections 最大连接数,NIO下默认值为10000,BIO(8.5版本废弃)下同maxThreads
Tuning Tomcat For A High Throughput, Fail Fast System
计算实际处理能力,当超出处理能力时尽量fail fast,防止影响全局性能