TCP(五) -- 连接队列

371 阅读4分钟

一:摘要概述

客户端与服务端创建连接的过程称之为三次握手,三次握手过程中状态的变更以及数据信息的交互在系列文章TCP(二) -- 三次握手中已经详细阐述。但是是否思考过一个问题,服务端如何处理SYN、ACK后的连接

二:连接队列

在这里插入图片描述

  • syns queue:半连接队列,存储SYN后的连接
  • accept queue:全连接队列,存储ACK后的连接

当客户端Client发送SYN包给服务端时,服务端会将连接信息存储到半连接队列,服务端回复SYN+ACK。客户端获取SYN+ACK数据包处理并回复ACK,服务端获取到客户端ACK后由半连接队列中取出连接信息处理存储到全连接队列。全连接队列中的连接就可以等待应用程序使用取出

三:连接控制

连接队列大小肯定不可能无限大,控制连接队列大小就是需要关注的一个核心问题,这关系着应用可承载压力。两个核心的数值如下:

  • backlog:程序控制的参数,指定连接队列大小。Java默认50、Nginx/Redis等默认511
  • somaxconn:系统参数,CentOS默认数值128

backlog调用函数accept()时可以指定,但是系统不会直接选取该值作为连接队列大小。而是会根据系统参数somaxconn结合考虑。其选取标准为min(backlog,somaxconn),如下图所示,通过Tomcat发布的应用,其中Tomcat设置连接数量参数为800,但是最后查询显示也仅仅是128。128是系统参数somaxconn的默认值,修改路径为/pro/sys/net/core/somaxconn

在这里插入图片描述
在这里插入图片描述

四:连接策略

当连接队列充满时有新的连接进入,这时候服务端会如何进行处理?这个策略由参数/proc/sys/net/ipv4/tcp_abort_on_overflow控制。其默认值为0,具体的策略如下描述:

  • 0:全连接队列溢出,服务端Server扔掉客户端Client发送的数据包信息
  • 1:全连接队列溢出,服务端发送RST包到客户端Client强制断开连接

当参数设定为1的时候服务端会发送RST包到客户端,所以对于客户端来讲至少是知道连接失败的信息。但是当参数值设置为0的时候客户端并不知道连接失败,Client判断为连接成功处于ESTABLISHED状态会向服务端发送数据,如下图所示:

在这里插入图片描述
上图所示当客户端认定连接状态处于正常情况下发送数据服务端会丢弃该数据包不做任何处理,这时候客户端会进行重 试传输,重试的次数由参数/proc/sys/net/ipv4/tcp_retries2控制。具体的超时重传策略将会在后续文章中进行解释。对于客户端的操作已经比较清晰的情况下可以思考服务端的操作,服务端此时认定连接并未成功,操作如下图所示:
在这里插入图片描述
服务端会重走三次握手的第二步,向客户端传输SYN+ACK

五:泄漏排查

进行压测的过程中如果遇到间断性连接获取不到,亦或是出现连接无响应的情况。但是查看机器的CPU等数据参数状况正常,压力还是上不去,注意了这时候你就需要排查连接队列是否存在溢出的情况

[root@bogon ~]# netstat -s | egrep "listen|LISTEN" 
    4972416 times the listen queue of a socket overflowed
    4972416 SYNs to LISTEN sockets ignored

上述命令可以查看到服务器连接队列情况,如果该数据持续上升就可以印证存在队列溢出的情况,就需要调整相关参数

[root@bogon ~]# ss -s
Total: 4759 (kernel 4831)
TCP:   4533 (estab 4087, closed 204, orphaned 6, synrecv 0, timewait 32/0), ports 2460

Transport Total     IP        IPv6
*         4831      -         -        
RAW       0         0         0        
UDP       8         5         3        
TCP       4329      12        4317     
INET      4337      17        4320     
FRAG      0         0         0

使用ss -s命令可以查看到具体的服务器上连接信息,当然ss命令还可以查看很多内容。常用参数作用如下:

序列编码 参数名称 参数作用
1 s 查询概要情况
2 a 显示所有套接字
3 l LISTEN 状态
4 t 查询TCP连接
5 u 查询UDP连接
6 n 不要翻译服务器名称
[root@bogon ~]# ss -alnt
State       Recv-Q Send-Q                Local Address:Port           Peer Address:Port 
LISTEN      0      100                   :::15345                     :::*     
LISTEN      0      1                     ::ffff:127.0.0.1:15217       :::* 

其中Send-Q参数表示全连接队列的大小,Recv-Q表示全连接队列使用的数量