You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UDP丢包原因排查:双服务器多网卡C++应用问题咨询

UDP跨服务器转发丢包排查与实践疑问解答

问题背景与环境

  • 两台服务器X、Y,各配备双网卡:X的x1、x2;Y的y1、y2。其中x2与y2处于同一局域网,x1、y1分别用于接收UDP组播数据包。
  • 两台服务器部署了相同的C++应用,以X为例的核心逻辑:
    1. 线程1(绑定独立CPU核心):以非阻塞模式打开socket绑定x1,循环调用recvfrom()接收组播包,通过同一socket调用sendto()转发至Y的y2网卡IP,最后将数据存入并发队列。
    2. 线程2(绑定独立CPU核心):以非阻塞模式打开socket绑定x2,接收Y转发的数据包后存入同一并发队列。
    3. 线程3(绑定独立CPU核心):消费并发队列中的数据,执行业务逻辑。

核心疑问

  1. 在同一线程的同一socket上同时执行收发操作是否为不良实践?如果是,更优方案是什么?
  2. 若tcpdump捕获的数据包数量与应用接收的数量一致,是否可以排除因两次recvfrom()调用间隔过长导致的丢包?
  3. 若发送端服务器tcpdump捕获了100个出站数据包,而接收端仅捕获95个入站数据包,该如何定位丢失的5个数据包?它们可能丢失在哪些网络层?

已完成排查与数据

  • x2和y2的tcpdump结果显示:Y的y2接收的数据包数量少于X的x2发送的数量,反向转发也存在类似情况;其中X到Y的数据包频率更高(约10个/秒)、尺寸更大(256字节),丢包率也更高。
  • 两台服务器的默认接收缓冲区(通过cat /proc/sys/net/core/rmem_default查看)均为212992。
  • netstat -suna显示以下UDP相关指标无增长:
    • packets to unknown port received
    • packet receive errors
    • receive buffer errors
    • send buffer errors
  • 使用sockperf在x2与y2之间测试,在更高消息频率和吞吐量设置下无丢包。

问题解答

1. 同一线程同一socket同时收发是否为不良实践?

这是不推荐的实践,核心问题有两点:

  • 收发操作相互干扰:即使是非阻塞socket,sendto()也可能因发送缓冲区满返回EAGAIN或进入短暂等待,会挤占recvfrom()的执行时间,导致组播包接收不及时,增大丢包概率。
  • 逻辑耦合度高:同一socket绑定x1网卡做组播接收,同时用它向y2转发,会让socket的网络属性(如绑定网卡、组播订阅)与转发逻辑绑定,后续维护和排查问题的成本会很高。

更优方案:

  • 拆分收发socket:线程1单独创建两个非阻塞socket,一个绑定x1专门负责组播接收,另一个专门用于向y2转发数据(可绑定x2网卡,避免跨网卡转发的额外开销)。
  • 转发逻辑异步化:如果转发压力较大,可将转发任务放入单独的并发队列,由专门的转发线程处理,避免占用接收线程的CPU时间。

2. tcpdump捕获数与应用接收数一致,能否排除recvfrom()间隔过长的丢包?

可以基本排除这种情况,原因如下:

  • tcpdump是在网卡驱动层捕获数据包,只要tcpdump能抓到,说明数据包已经到达服务器并进入内核缓冲区。
  • 若recvfrom()间隔过长,会导致内核接收缓冲区被占满,此时内核会丢弃新数据包,这种情况下tcpdump依然能抓到包,但应用接收不到,两者数量会出现差异。
  • 既然两者数量一致,说明内核缓冲区没有因应用处理不及时而溢出,recvfrom()的间隔处于合理范围。

3. 发送端抓包100个、接收端仅95个,如何定位丢包?

这种丢包发生在发送端网卡之后、接收端网卡之前的网络路径中,可能涉及的层级和排查步骤如下:

可能的丢包层级

  • 数据链路层:局域网交换机端口拥塞、MAC地址学习异常、链路故障(如网线松动、网卡协商速率不匹配)。
  • 网络层:VLAN配置异常、ARP缓存失效(虽然是同一局域网,但可能存在ARP表项过期或错误)。
  • 传输层基本可排除:因为应用能收到部分包,且netstat无未知端口相关指标增长,说明接收端UDP端口正常监听。

定位步骤

  1. 在中间网络设备抓包:如果局域网有管理型交换机,在X的x2连接的交换机端口和Y的y2连接的端口同时抓包,确认数据包是否成功离开X所在端口、是否到达Y所在端口。
  2. 检查服务器网卡状态:
    • 查看网卡硬件卸载功能:执行ethtool -k x2、ethtool -k y2,TSO/GRO等卸载功能可能导致数据包在网卡层丢失,可临时关闭后测试。
    • 查看网卡错误统计:执行ethtool -S x2、ethtool -S y2,检查rx_errors、tx_errors、dropped等指标是否增长。
  3. 调整包参数测试:你已经发现大尺寸、高频率的包丢包率更高,可进一步降低包大小或频率,验证丢包是否缓解,判断是否是链路带宽或缓冲区不足导致。
  4. 调大网络栈缓冲区:虽然默认接收缓冲区为212992,可临时调大接收缓冲区上限:sysctl -w net/core/rmem_max=4194304,同时在应用中通过setsockopt()设置SO_RCVBUF参数,验证是否能降低丢包。

内容的提问来源于stack exchange,提问作者AlgRev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:20:47