- A+
所属分类:linux技术
目录
三次握手
- 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
(将连接放入半连接队列中)
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
(连接从半连接队列移出,移入全连接队列中。)
当服务端端调用accept()时,会将连接从全连接队列中取出。
半连接队列和全连接队列的大小
syns queue大小
max(64,/proc/sys/net/ipv4/tcp_max_syn_backlog)
accept queue大小
accept queue大小取决于:min(backlog,somaxconn),
-
backlog由listen()函数的backlog决定
thrift中默认的backlog大小为1024
-
somaxconn则是内核参数:/proc/sys/net/core/somaxconn
somaxconn默认为128
查看全连接队列大小
ss -lnt 'sport=:10240' Stae Recv-Q Send-Q Local Address:port LISTEN 0 128 *:10240
Send-Q:全连接队列(accept queue)的最大值,其值为min(backlog,somaxconn)
Recv-Q:已建立成功(状态为ESTABLISHED),但尚未交付给应用的“tcp连接的数量”,其最大值为Send-Q+1。(即三次握手完成,但是服务端还没有调用accept从全连接中取出的连接数量----积压数量)
netstat -anp |grep 10240
accept queue队列满之后协议栈的处理策略
cat /proc/sys/net/ipv4/tcp_abort_on_overflow #有效值为:0或1
- 0:当tcp建立连接的3次握手完成后,将连接置为ESTABLISHED状态并交付给应用程序的backlog队列时,会检查backlog队列是否已满。若已满,通常行为是将连接还原至SYN_ACK状态,以造成3次握手最后的ACK包意外丢失的假象,这样在客户端等待超时后可重发ACK,以再次尝试进入ESTABLISHED状态,作为一种修复、重试机制。
- 1:如果tcp_abort_on_overflow为1,则在检查到backlog队列已满时,直接发RST包给客户端终止此连接。此时客户端程序会收到104 Connection reset by peer错误。
全连接队列、半连接队列溢出的问题很容易被忽略,但是又很关键,特别是对于一些短连接应用更容易爆发。一旦溢出,从CPU、线程状态看都正常,但是压力上不去。
如何定位客户端异常与连接队列满有关
为了证明客户端应用程序异常跟全连接队列满有关系,可以先把tcp_abort_on_overflow参数修改为1,接着测试如果在客户端异常中可以看到很多connection reset by peer错误,说明客户端错误是连接队列满导致的。
或者
netstat -s|grep "listen|LISTEN" 3 times the listen queue of a socket overflowed s SYNs to LISTEN sockets dropped
说明发生了3次全连接队列溢出。