5

我有一个通过多播发送 UDP 数据包的服务器和一些列出这些多播数据包的客户端。每个数据包的大小固定为 1040 Bytes,服务器发送的整个数据大小为 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% 以下,因此处理起来不成问题。

4

3 回答 3

4

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

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

于 2016-06-23T01:30:04.057 回答
2

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

  • 增加套接字接收缓冲区setsockopt(2)
  • 如果您的内核支持,请使用recvmmsg(2)来减少系统调用和内核用户态副本的数量,
  • 考虑边缘触发的非阻塞方法epoll(7)
  • 看看你是否真的需要线程,锁定/同步非常昂贵。
于 2012-06-05T15:36:06.887 回答
-1

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

于 2016-03-01T09:35:12.050 回答