Linux内核导致的UDP数据包丢失问题

5
我有一台服务器通过组播发送UDP数据包,并且有许多客户端监听这些组播数据包。每个数据包的大小固定为1040字节,服务器发送的整个数据大小为3GB。
我的环境如下:
1 Gbit以太网网络
40个节点,1个发送节点和39个接收节点。所有节点具有相同的硬件配置:2个AMD CPU,每个CPU有2个核心@2.6GHz
在客户端,一个线程读取套接字并将数据放入队列中。另一个额外的线程从队列中弹出数据并进行轻量级处理。
在组播传输期间,我注意到节点端的数据包丢失率为30%。通过观察netstat -su统计信息,我可以说,客户端应用程序丢失的数据包等于netstat输出的RcvbufErrors值。
这意味着所有缺失的数据包都被操作系统丢弃,因为套接字缓冲区已满,但我不明白为什么捕获线程无法及时读取缓冲区。在传输期间,4个核心中的2个核心利用率为75%,其余的处于睡眠状态。
我是唯一使用这些节点的人,我认为这种机器没有处理1Gbit带宽的问题。我已经进行了一些优化,通过为amd cpus添加g ++编译器标志,将数据包丢失率降低到10%,但我认为这仍然太高了。
当然,我知道UDP不可靠,我有自己的纠错协议。
我没有任何管理权限,因此无法更改系统参数。
有什么提示可以提高性能吗?
编辑:
我通过使用2个线程读取套接字来解决此问题。接收套接字缓冲区有时仍会变满。但平均掉落率低于1%,因此处理它不是问题。

你可以调查一下是否支持巨型帧,并发送更多的数据到每个数据包中,从而降低节点需要处理的中断数量。在最坏的情况下,网络驱动程序可能不够好。 - HonkyTonk
3个回答

5
追踪Linux上的网络掉包可能有些困难,因为出现数据包丢失的组件很多。它们可能发生在硬件层面、网络设备子系统中或协议层中。
我写了一篇非常详细的博客文章,解释了如何监控和调整每个组件。由于需要监控和调整的不同组件太多,因此很难在这里用简洁的答案进行总结。您可以查看详细的博客文章

2

除了从套接字读取循环中删除所有非必要的内容之外:

  • 使用setsockopt(2)增加套接字接收缓冲区,
  • 如果您的内核支持,使用recvmmsg(2)来减少系统调用和内核-用户空间拷贝的数量,
  • 考虑使用边缘触发的epoll(7)进行非阻塞处理,
  • 看看你是否真的需要线程,锁定/同步非常昂贵。

仅为第一条提供完整性:(1)内核可能会限制大小-因此请查阅/proc/sys/net/core/rmem_max,以及(2)setsockoptoptvalSO_RCVBUF - nhed

-1
在客户端,一个线程读取套接字并将数据放入队列中。 我猜问题出在这个线程上。它没有快速地接收消息。太多时间花费在其他事情上,例如在将数据放入队列时获取互斥锁。尝试优化队列操作,例如使用无锁队列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接