Rootop 服务器运维与web架构

backlog全连接队列和半连接队列

[root@localhost ~]# man listen 查看listen方法的文档

名称:
listen – listen for connections on a socket 在一个套接字上倾听连接

概述:
#include <sys/socket.h>
int listen(int s, int backlog);

描述:
在接收连接之前,首先要使用 socket(2) 创建一个套接字,然后调用 listen 使其能够自动接收到来的连接并且为连接队列指定一个长度限制.
之后就可以使用 accept(2) 接收连接. listen 调用仅适用于 SOCK_STREAM 或者 SOCK_SEQPACKET 类型的套接字.

参数 backlog 指定未完成连接队列的最大长度.如果一个连接请求到达时未完成连接 队列已满,那么客户端将接收到错误 ECONNREFUSED.
或者如果下层协议支持重发,那么这个连接请求将被忽略,这样客户端在重试的时候就有成功的机会.

注意:
在TCP套接字中 backlog 的含义在Linux 2.2中已经改变.它指定了已经完成连接正等待应用程序接收的套接字队列的长度,而不是未完成连接的数目.
未完成连接套接字队列 (半连接,SYN_RCVD状态) 的最大长度可以使用 /proc/sys/net/ipv4/tcp_max_syn_backlog 或者 sysctl 中设置
当打开syncookies时不存在逻辑上的最大长度,此设置将被忽略.参见 tcp(7) 以获取更多信息.

也就是说 backlog 是限制处于 全连接,ESTABLISHED(已完成三次握手) 状态但未由应用程序处理的队列值。

# 查看某个服务的backlog值,比如python写的socket服务,端口为1111

[root@localhost ~]# ss -ln | grep -E "1111|Netid"
Netid   State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port                                                                            
tcp     LISTEN   0        128      0.0.0.0:1111         0.0.0.0:*   

通过 Send-Q 列可以看到1111端口服务的backlog值为128,也就是默认系统的值。

[root@localhost ~]# cat /proc/sys/net/core/somaxconn
128

当然,这个值可以通过 sysctl.conf 中添加配置进行修改。

net.core.somaxconn=1024

(somaxconn 推测是 socket max connection 缩写)

# python 服务端代码
import socket

ADDRESS = ('0.0.0.0', 1111)
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
socket.bind(ADDRESS)
socket.listen(10)

如果在socket编程中,设置listen() 值为10,那么再次查看会变为10

[root@localhost ~]# ss -ln | grep -E "1111|Netid"
Netid   State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port                                                                            
tcp     LISTEN   0        10       0.0.0.0:1111         0.0.0.0:*   

注意:socket.listen()方法中的值和内核参数/proc/sys/net/core/somaxconn中的值会取最小值做为最大队列长度。

# 查看指定服务当前已用的队列数
上面的Recv-Q列,当state状态为LISTEN时,为已建立的全连接大小。

注意: ss 命令获取的 Recv-Q/Send-Q 在「LISTEN 状态」和「非 LISTEN 状态」所表达的含义是不同的
在ss -nt时,两列含义:
Recv-Q 连接此套接字的用户程序未拷贝的字节数。
Send-Q 远程主机未确认的字节数。

# 查看半连接队列数
半连接队列没有什么命令可以直接看,不过可以通过netstat计算SYN_RECV数量

[root@localhost ~]# netstat -antp | grep SYN_RECV | wc -l

半连接丢弃的3个条件,并不是单纯由max_syn_backlog 参数决定,可参考:https://www.toutiao.com/i6833215977505686028
1、如果半连接队列满了,并且没有开启 tcp_syncookies,则会丢弃;
2、若全连接队列满了,且没有重传 SYN+ACK 包的连接请求多于 1 个,则会丢弃;
3、如果没有开启 tcp_syncookies,并且 max_syn_backlog 减去 当前半连接队列长度小于 (max_syn_backlog >> 2),则会丢弃;
>> 符号为c语言里的位移

原创文章,转载请注明。本文链接地址: https://www.rootop.org/pages/4842.html

作者:Venus

专注于 服务器运维与web架构 E-mail:venus#rootop.org

评论已关闭。