UDP内核丢弃UDP数据包

时间:2012-06-05 15:11:13

标签: linux udp multicast packet-loss

我有一台服务器通过多播发送UDP数据包和许多列出这些多播数据包的客户端。 每个数据包的固定大小为1040字节,服务器发送的整个数据大小为3GByte。

我的环境如下:

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个读取套接字的线程解决了这个问题。 recv套接字缓冲区有时仍会变满。但平均跌幅低于1%,所以处理它不是问题。

3 个答案:

答案 0 :(得分:3)

跟踪Linux上的网络丢失可能有点困难,因为有许多组件可能会发生丢包。它们可以在硬件级别,网络设备子系统或协议层中发生。

我写了一篇非常detailed blog post来解释如何监控和调整每个组件。由于有许多不同的组件需要进行监控和调整,因此有点难以总结为一个简洁的答案。

答案 1 :(得分:2)

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

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

答案 2 :(得分:-1)

"在客户端,一个线程读取套接字并将数据放入队列。 " 我猜问题出在这个帖子里。它没有足够快地接收消息。在其他方面花费了太多时间,例如在将数据放入队列时获取互斥锁。尝试优化队列上的操作,例如使用无锁队列。