af_inet.c#inet_listen() -> inet_connection_sock.c#inet_csk_listen_start() -> request_sock.c#reqsk_queue_alloc()
reqsk_queue_alloc() 函数代码如下 , 主要就是用来计算半连接队列大小的 。
文章插图
计算逻辑可以简化为下述公式 , 简单描述 roundup_pow_of_two 算法就是向上取最接近的最大 2 的指数次幂 , 注意此处 backlog 已经是 min(backlog, somaxconn)
半连接队列大小 = roundup_pow_of_two(max(8, min(backlog, tcp_max_syn_backlog))+1)
代码里 max_qlen_log 在一个 for 循环里计算 , 比如算出的半连接队列大小 nr_table_entries = 16 = 2^4 , 那么 max_qlen_log = 4 , 该值在判断半连接队列是否溢出时会用到 。
举个例子 , 如果 listen backlog = 10、somaxconn = 128、tcp_max_syn_backlog = 128 , 那么半连接队列大小 = 16 , 全连接队列大小 = 10 。
所以要知道 , 在做连接队列大小调优的时候 , 一定要综合上述三个参数 , 只修改某一个起不到想要的效果 。
连接队列大小查看全连接队列大小
【Tomcat 调优之从 Linux 内核源码层面看 Tcp backlog】可以通过 linux 提供的 ss 命令来查看全连接队列的大小
文章插图
参数说明 , 参数很多 , 其他参数可以自己 help 查看说明
l:表示显示 listening 状态的 socket这个命令结果怎么解读呢?
n:不解析服务名称
t:只显示 tcp sockets
主要看前三个字段 , Recv-Q 和 Send-Q 在 State 为 LISTEN 和非 LISTEN 状态时代表不同的含义 。
State: LISTEN
Recv-Q: 全连接队列的当前长度 , 也就是已经完成三次握手等待服务端调用 accept() 方法获取的连接数量
Send-Q: 全连接队列的最大长度 , 也就是我们上述分析的 backlog 和somaxconn 的最小值
State: 非 LISTEN以上区别从如下内核代码也可以看出 , ss 命令就是从 tcp_diag 模块获取的数据
Recv-Q: 已接受但未被应用进程读取的字节数
Send-Q: 已发送但未收到确认的字节数
文章插图
半连接队列大小
半连接队列没有像 ss 这种命令直接查看 , 但服务端处于 SYN_RECV 状态的连接都在半连接队列里 , 所以可以通过如下命令间接统计
netstat -natp | grep SYN_RECV | wc -l
半连接队列最大长度可以使用我们上述分析得到的公式计算得到半全连接队列溢出全连接队列溢出
当请求量很大 , 全连接队列比较小时 , 就有可能发生全连接队列溢出的情况 。
此代码是 linux 内核用来判断全连接队列是否已满的函数 , 可以看到判断用的是大于号 , 这也就是我们用 ss 命令可能会看到 Recv-Q > Send-Q 的原因
- sk_ack_backlog 是当前全连接队列的大小
- sk_max_ack_backlog 是全连接队列的最大长度 , 也就是 min(listen_backlog, somaxconn)
文章插图
当全连接队列满了发生溢出时 , 会根据 /proc/sys/net/ipv4/tcp_abort_on_overflow 内核参数来决定怎么处理后续的 ack 请求 , tcp_abort_on_overflow 默认值为 0 。
- 当 tcp_abort_on_overflow = 0 时 , 如果全连接队列已满 , 服务端会直接扔掉客户端发送的 ACK , 此时服务端处于 SYN_RECV 状态 , 客户端处于 ESTABLISHED 状态 , 服务端的超时重传定时器会重传 SYN + ACK 包给客户端(重传次数由/proc/sys/net/ipv4/tcp_synack_retries 指定 , 默认值为 5 , 重试间隔为 1s、2s、4s、8s、16s , 共 31s , 第 5 次发出后还要等 32s 才知道第 5 次也超时了 , 所以总共需要 63s) 。超过 tcp_synack_retries 后 , 服务端不会在重传 , 这时如果客户端发送数据过来 , 服务端会返回 RST 包 , 客户端会报 connection reset by peer 异常
经验总结扩展阅读
- 【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和
- 地下城堡3:魂之诗10月9日礼包兑换码是什么
- 在没有发明眼镜之前眼镜蛇叫什么
- 怎么能让榴莲一夜之间催熟
- 仅仅是因为寂寞而凑合在一起的星座配对
- 2023年2月20日安门好吗
- 12月这3个星座将会财神偏爱 求财之路顺畅
- flutter系列之:builder为构造器而生
- 王者荣耀妲己时之奇旅皮肤的台词都有什么
- 地下城堡2:黑暗觉醒图28漩涡之底怎么通关