并发连接同一地址超时问题
今天和duolong一起追查connect超时问题,结果发现是arp pending queue len的原因;
1. 现象描述
现象a:自己写的client程序,开启16个socket并发connect同一server(异步框架,超时时间为2s),结果其中3个socket连接成功,其余13个超时失败;
现象b:一次试验后,接下来多次连续试验都会成功(不出现超时现象);
现象c:停止试验一段时间后,再次试验,现象同b;
现象d:每次试验前,主动删除相应server的arp条目(arp -d server-ip),问题稳定复现;
现象e:抓包结果如下,arp请求成功后,3个socket的syn包立刻发出;13个socket的syn包,3s后才发出;
2. 原因追查
根据上述现象,查看2.6.32源码,围绕arp相关(neighbour)的代码,发现arp模块有个queue(neigh->parms->queue_len)长度默认为3,该队列用于存储arp尚未成功pengding的skb,如,我们试验中的syn包;如果因arp pending的skb超过3,则arp模块会丢弃queue中老的skb。
源码路径:neigh_resolve_output()->neigh_event_send()->__neigh_event_send()
源码片段:
if (neigh->nud_state == NUD_INCOMPLETE) {
if (skb) {
if (skb_queue_len(&neigh->arp_queue) >=
neigh->parms->queue_len) {
struct sk_buff *buff;
buff = __skb_dequeue(&neigh->arp_queue);
kfree_skb(buff);
NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
}
__skb_queue_tail(&neigh->arp_queue, skb);
}
分析:16个并发connect的syn包,由于arp失效/重新请求,只有最后的3个保存在queue中(与上图中成功的syn包端口号最大的现象吻合),其余13个被丢弃,tcp层3s后重传13个syn包(netstat -s | grep timeout,超时重传计数增大13);另外,查看“NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards”)相关的ures_discards计数也增大13;
相关参数:neigh->parms->queue_len 可以通过/proc/sys/net/ipv4/neigh/eth0/unres_qlen调节大小;
unres_discards计数可以通过/proc/net/stat/arp_cache (unresolved_discards的值)查看(注意该计数是per cpu的);
3. 解决方法
增大arp pending queue len, echo 32 > /proc/sys/net/ipv4/neigh/eth0/unres_qlen;
4. 快速复现方法
下面提供一个简单的复现上述问题的方法;
第一步:删除相应arp cache, 命令: arp -d server-ip
第二步:发送多个数据包长度的ping,命令:ping -c 2 -s 8000 server-ip
原文链接:http://blog.sina.com.cn/u/2015038597
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?