内核会为 listen 状态的 socket 维护两个队列:不完全连接请求队列(SYN_RECV)和等待 accept() 建立的队列,就是已完成连接队列(ESTABLISHED);
accept函数由TCP服务器调用,用于从已完成连接队列队头返回下一个已完成连接;
accept在三次握手之后。
TCP三次握手中:
第一步,server收到client的syn后,server把这个连接信息放到半连接队列中,;
第二步,server回复syn+ack给client;
第三步,server收到client的ack,这时如果全连接队列没满,server就从半连接队列拿出这个连接的信息放入到全连接队列中,否则按net.ipv4.tcp_abort_on_overflow指示的执行。
这时如果全连接队列满了并且net.ipv4.tcp_abort_on_overflow是0的话,server过一段时间再次发送syn+ack给client,重试的次数由net.ipv4.tcp_synack_retries决定。
几个内核参数
net.ipv4.tcp_abort_on_overflow
为0,表示TCP握手第三步的时候如果全连接队列满了那么server扔掉client 发过来的ack,在server端认为连接还没建立起来,
server过一段时间再次发送syn+ack给client(也就是重新走握手的第二步),如果client超时等待比较短,client就很容易异常了;
为1,表示第三步的时候如果全连接队列满了,server发送一个reset包给client,表示废掉这个握手过程和这个连接,
这时在客户端异常中一般会看到connection reset by peer的错误
net.ipv4.tcp_synack_retries
TCP三次握手后有个accept全连接队列,进到这个队列才能从Listen变成accept,这个队列满的话,server端如果要重发syn+ack给client,
net.ipv4.tcp_synack_retries表示重试次数
net.ipv4.tcp_max_syn_backlog
端口最大 backlog 内核限制,是指定所能接受SYN同步包的最大客户端数量,即半连接上限(sync queue大小),centos默认128。
动机是在内存有限的服务器上限制/避免应用程序配置超大 backlog 值而耗尽内核内存。
如果应用程序设置 backlog 大于此值,操作系统将自动将之限制到此值。
net.ipv4.somaxconn
是指服务端所能accept即处理数据的最大客户端数量,即完成连接上限(accept queue大小),centos默认128
tcp_syncookies
在 tcp 建立连接的 3 路握手过程中,当服务端收到最初的 SYN 请求时,会检查应用程序的 syn_backlog 队列是否已满。
若已满,通常行为是丢弃此 SYN 包。若未满,会再检查应用程序的 backlog 队列是否已满。
若已满并且系统根据历史记录判断该应用程序不会较快消耗连接时,则丢弃此 SYN 包。
如果启用 tcp_syncookies 则在检查到 syn_backlog 队列已满时,不丢弃该 SYN 包,而改用 syncookie 技术进行 3 路握手。