UDP数据包由linux内核丢弃

我有一个服务器,通过多播发送UDP数据包和一些列表到这些多播数据包的客户端。 每个数据包的固定大小为1040字节,服务器发送的全部数据量为3GB。

我的环境如下:

1千兆比特以太网

40个节点,1个发送者节点和39个接收器节点。 所有节点具有相同的硬件configuration:2个AMD CPU,每个CPU有2个2.6GHz的内核

在客户端,一个线程读取套接字并将数据放入队列中。 一个额外的线程从队列中popup数据并执行一些轻量级处理。

在组播传输期间,我认识到节点端的丢包率为30%。 通过观察netstat -su统计信息,我可以说,客户端应用程序丢失的数据包等于netstat输出中的RcvbufErrors值。

这意味着所有丢失的数据包都被操作系统丢弃,因为套接字缓冲区已满,但我不明白为什么捕获线程无法及时读取缓冲区。 在传输过程中,4个核心中的2个被利用了75%,其余的正在睡觉。 我是唯一一个正在使用这些节点的人,而且我认为这种机器在处理1Gbit带宽方面没有问题。 我已经做了一些优化,通过为amd cpus添加g ++编译器标志,这将数据包丢失率降低到10%,但是在我看来,它仍然太高。

当然我知道UDP是不可靠的,我有自己的修正协议。

我没有任何pipe理权限,因此我无法更改系统参数。

任何提示如何提高性能?

编辑:我解决了这个问题,使用2线程正在读取套接字。 有时recv套接字缓冲区仍然变满。 但平均下降不到1%,所以处理它不是问题。

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

我写了一篇非常详细的博客文章,解释如何监控和调整每个组件。 这里简单的回答有点困难,因为有太多不同的组件需要监视和调整。

除了从套接字读取循环中清除所有非必要的东西外:

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

“在客户端,一个线程读取套接字并将数据放入队列中。”我猜这个问题是在这个线程中。 它不够快速地接收消息。 花费太多时间在别的东西上,例如在将数据放入队列时获取互斥体。 尝试优化队列上的操作,例如使用无锁队列。