问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

一个问题带你了解半/全连接队列

发布网友 发布时间:2024-10-04 01:08

我来回答

1个回答

热心网友 时间:2024-10-04 01:05

最近项目上遇到一个问题,运维反馈有一个服务会不定时出现健康检查异常,于是去排查了一下。问题最终发现和半连接、全连接队列大小有关,所以打算好好研究一下。

(本文涉及的Linux内核源码以v3.10为主)

一个偶发的线上问题

该项目通过WebSocket对外提供服务,每次出现异常时,都会伴随一些现象发生:

健康检查提示请求超时。

通过监控发现在异常时间段,有大量状态码是101的HTTP请求,并且upstream_time时间较长。

可以看出,当时有大量客户端同时进行WebSocket建连,而该项目的健康检查机制是通过TCP进行端口建连来判断服务是否健康,很大可能是实例短时无法承载大量建连导致异常。

和并发建连有关的参数,首先想到的就是半连接、全连接队列,于是登录到容器中通过netstat -s查看两个队列是否有溢出。

可以看到半连接、全连接队列均有溢出的情况,所以可以初步推断是这两个队列大小的问题,最终通过扩大全连接队列的大小也解决了这个问题。

那么,到底什么是半/全连接队列呢?

什么是半/全连接队列

在TCP三次握手进行建连的过程中,Linux内核会通过这两个队列来进行连接过程状态的缓存和维护。

半连接队列,也称SYN队列,当服务端收到客户端发来的SYN请求后,就会将该连接存储到半连接队列中,并向客户端回复SYN+ACK。

全连接队列,也称ACCEPT队列,当服务端收到ACK回复,完成三次握手后,就会将该连接从半连接队列中移除,放入全连接队列中,等待应用进程调用accept()取走连接。

对应的过程如下:

半连接队列半连接队列大小

主要受两个参数的影响,backlog和tcp_max_syn_backlog。

在Linux内核源码中,半连接队列的空间分配在 net/core/request_socket.c 中的reqsk_queue_alloc()方法里进行,队列大小计算逻辑如下:

//其中,nr_table_entries记录最终队列大小nr_table_entries?=?min_t(u32,?nr_table_entries,?sysctl_max_syn_backlog);nr_table_entries?=?max_t(u32,?nr_table_entries,?8);nr_table_entries?=?roundup_pow_of_two(nr_table_entries?+?1);

队列大小受两个参数影响:

backlog。源码中,nr_table_entries 的初始值为服务端 listen() 时传入的backlog;

sysctl_max_syn_backlog。该参数即是系统参数tcp_max_syn_backlog,通过sysctl可以查看和设置(源码中默认为256)。

队列大小会取两者的最小值,同时必须大于等于8,并将得到的结果进行 roundup_pow_of_two 运算,该操作会找到当前数值的二进制最高位数n,然后以1循环右移n次作为结果集,简单理解就是按2的倍数向上取整。

举个栗子,如果backlog设置为128,sysctl_max_syn_backlog配置为64,则计算过程简化如下:

半连接队列大小?=?roundup_pow_of_two(min(128,?64))?=?128半连接队列溢出的条件

在内核源码 net/ipv4/tcp_ipv4.c 的 tcp_v4_conn_request() 方法中,半连接队列有两个主要的场景:

半连接队列满了,且未开启 syn_cookies

if?(inet_csk_reqsk_queue_is_full(sk)?&&?!isn)?{??want_cookie?=?tcp_syn_flood_action(sk,?skb,?"TCP");??if?(!want_cookie)??????goto?drop;}

(关于 syn_cookies ,我们之后单独介绍)

全连接队列满了,且半连接队列中有待回复 SYN+ACK 的连接

if?(sk_acceptq_is_full(sk)?&&?inet_csk_reqsk_queue_young(sk)?>?1)?{??NET_INC_STATS_BH(sock_net(sk),?LINUX_MIB_LISTENOVERFLOWS);??goto?drop;}

可以看到这种情况下,不仅半连接队列溢出+1,全连接队列溢出也会+1。

半连接溢出的场景

短时间内大量并发建连,队列空间不足以存放收到的SYN包;

全连接队列已满,半连接队列直接丢弃新的SYN包(即使当前仍有空间);

建连时间过长,半连接队列积压导致溢出。

全连接队列全连接队列大小

全连接队列大小的分配在 net/socket.c 中,计算逻辑如下:

somaxconn?=?sock_net(sock->sk)->core.sysctl_somaxconn;if?((unsigned?int)backlog?>?somaxconn)?{????backlog?=?somaxconn;}

队列大小受两个参数影响:

backlog。由服务端 listen() 时传入的backlog决定。

sysctl_somaxconn。该参数同样为系统参数,通过sysctl可以查看和设置(源码中默认为128)。

全连接队列大小会设置为backlog和somaxconn中较小的值。

全连接队列溢出的条件

全连接对出的判断就比较简单了,在 net/ipv4/tcp_ipv4.c 中进行了判断:

if?(sk_acceptq_is_full(sk))????goto?exit_overflow;

即在完成了三次握手,得到一个有效的synack时,如果发现全连接队列满了,则将其丢弃。

全连接队列溢出的场景

短时间内大量连接完成三次握手,队列放不下;

业务层accept()速度较慢,全连接队列积压。

如何判断队列是否溢出

判断的方法很多,例如ss、netstat、/proc/net/netstat,这里主要介绍netstat,通过-s参数可以查看到所有网络统计信息。

netstat?-s...????85336?times?the?listen?queue?of?a?socket?overflowed??//全连接队列溢出的累计次数????206804?SYNs?to?LISTEN?sockets?dropped??//半连接队列溢出的累计次数...

netstat 是如何统计这些信息的?

看了一眼 netstat 的源码,也是从/proc/net/netstat中读取的。 其中的数据来源于内核计数,相关定义在内核源码的 net/ipv4/proc.c 中,当内核发现半/全连接队列满,会相应的计数+1,对应LINUX_MIB_LISTENDROPS和LINUX_MIB_LISTENOVERFLOWS。

问题如何解决

既然知道了是两个队列均有溢出,那么就先从队列大小看起。

前文有提到,半/全连接队列大小与几个参数有关,tcp_max_syn_backlog、somaxconn和端口监听时传入的backlog。

先来看看系统参数:

可以看到系统参数配置中,半/全连接队列的大小均是配置为4096,对于我们的服务来说并不小。

那么再看代码中传入的backlog,该服务是前端Node实现的连接层,listen时没有传入backlog参数,源码中会默认设置为511。

此时,半连接队列大小 = roundup_pow_of_two(min(4096, 511)) = 512全连接队列大小 = min(4096, 511) = 511 Socket 中两个队列的实际大小都偏小。

最终我们将backlog参数设置为与系统一致的4096后,就没有再出现队列溢出的问题。

当两个队列均没有溢出时,netstat的统计并不会有这两个结果,想要进一步确认也可以通过/proc/net/stat进行判断。

总结

如果了解半/全连接及基础的溢出判断方法,那么对于这一类问题的定位还是比较好解决的,先通过 netstat -s看半/全连接队列是否有溢出,再通过系统参数tcp_max_syn_backlog、somaxconn和监听参数backlog入参判断两个队列的实际大小是否合理。

但是,实际上遇到连接队列溢出的问题时并不好判断,本文更多通过一个简单的线上问题介绍半/全连接队列的概念。

想要了解更多半/全连接队列的问题,可以期待之后的实战及周边知识文章,持续更新中~

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
立秋后钓鱼什么风向好-立秋钓鱼风向怎么选 赱乂砉込儬 怎么读 "赱"读什么? 解决电脑无法搜索到iPhone热点的问题如何修复iPhone热点无法在电脑上显... 电脑搜不到iphone12热点 iphone开热点给电脑搜不到 国企的地产有哪些 国企下设公司是什么意思? 红加蓝加绿是什么色. 梦幻西游75级开三倍抓鬼一轮有多少经验 贾宝玉被打的根本原因是什么 所的扩词有哪些 在泰州贷款买房40万两个人交满一年的住房公积金20年还清每月还多少... 会计活动经费入什么 学术会议费入什么科目 单招是不是只要通过就可以不用高考啊? ...韩雪再无水花。假唱事件如此之多,为何观众独独对她零容忍?_百度知 ... 座谈会经费入什么科目 会议费费用计入什么科目 会议经费入什么科目 为什么别人打我电话显示已振铃? 什么是分散投资理论 连不上校园网? 氧化钙与二氧化碳反应条件是什么氧化钙与二氧化碳反应条件简单介绍 请高人指教,去马尔代夫是九月下旬去还是十月上旬去 中国对马尔代夫9月8日球票什么时间发售 2015年10月8号国足今晚几点打 吃什么骨折愈合得快 吃什么有利于骨折恢复 急急急!微信没有绑定任何东西。然后突然登陆微信密码错误。就申诉账号... 孩子胆小害怕怎么办 unturned新手攻略介绍_unturned新手攻略是什么 小孩子胆小怎么锻炼 《Unturned》新手图文教程介绍_《Unturned》新手图文教程是什么 Unturned未转变者新手真实生存教学攻略介绍_Unturned未转变者新手真实生... 《Unturned》新手注意事项及搜刮物资图文攻略介绍_《Unturned》新手注意... ...介绍_unturned新手枪、背包、食物获得方法是什么 《Unturned》单机开荒经验详细介绍介绍_《Unturned》单机开荒经验详细介 ... 霍尔果斯口岸出境攻略,出境旅游自驾攻略 出国攻略和流程,出境旅游旅行攻略 泰国游玩攻略及费用,泰国旅游什么路线好玩 夏天空调开多少度合适又省电 有没有比较靠谱的国产FPGA开发板公司参考下? FPGA使用MIG调用SODIMM内存条接口教程,提供vivado工程源码和技术... 黑色t恤搭什么颜色裤子 睾丸隐隐作痛会自愈吗 左侧睾丸隐隐约约的疼能自愈吗 睾丸肿痛能自愈吗 ...能玩什么网络游戏和什么单机游戏 能玩梦幻龙族2吗和乐高篇幅侠_百度... 梦幻龙族2怎样挂机?求大神指导挂机方法