【问题标题】:multicast packet loss - running two instances of the same application多播数据包丢失 - 运行同一应用程序的两个实例
【发布时间】:2011-10-01 10:41:28
【问题描述】:

在 Redhat Linux 上,我有一个多播侦听器来侦听一个非常繁忙的多播数据源。它自己运行完美,没有丢包。然而,一旦我使用完全相同的设置(相同的 src/dst IP 地址、sock 缓冲区大小、用户缓冲区大小等)启动同一应用程序的第二个实例,我开始看到两个实例的数据包丢失非常频繁。他们丢失了完全相同的数据包。如果我停止其中一个实例,剩下的一个会恢复正常而不会丢失任何数据包。

最初,我虽然是 CPU/内核负载问题,但可能无法足够快地将数据包从缓冲区中取出。于是我又做了一个测试。我仍然保持应用程序的一个实例运行。但随后在同一台计算机上启动了一个完全不同的多播侦听器,但使用第二个 NIC 卡并侦听不同但更繁忙的多播源。两个应用程序运行良好,没有任何数据包丢失。

所以看起来一张 NIC 卡的功能不足以支持两个多播应用程序,即使它们收听完全相同的内容。丢包问题的可能原因可能是,在这种情况下,NIC 卡驱动程序需要将传入的数据复制到两个 sock 缓冲区,而这个额外的复制任务对于以太网卡来说太多了,因此它会丢弃数据包。对这个问题有更深入的分析和任何可能的解决方案吗?

谢谢

【问题讨论】:

  • 真的很奇怪。 NIC 卡不会立即从 NIC 设备驱动程序复制到套接字。当 NIC 接收到多播帧时,多播服务例程将过滤并将数据包转发到协议栈例程。协议栈例程负责将 UDP 数据包复制到每个套接字缓冲区。如果让两个实例加入相同的多播地址但在不同的接口上会发生什么?
  • 我不能做这个测试,因为只有这个 NIC 端口连接到数据源。但是我所做的测试(在问题中提到)表明它应该可以工作。但我真的很想让它在同一张网卡上工作。

标签: udp multicast


【解决方案1】:

您基本上发现内核在扇出多播数据包方面效率低下。最坏的情况下,代码为每个传入的数据包分配两个新缓冲区,即 SKB 对象和数据包负载,并复制 NIC 缓冲区两次。

选择最好的情况,为每个传入的数据包分配一个新的 SKB,但数据包有效负载在两个套接字之间通过引用计数共享。现在想象一下当两个应用程序,每个应用程序都在自己的核心和单独的套接字上时会发生什么。对数据包有效负载的每次引用都会导致内存总线停止,而两个核心缓存都必须刷新和重新加载,并且每个应用程序都必须来回切换内核上下文以传递套接字有效负载。结果是糟糕的表现。

您不是第一个遇到此类问题的人,许多供应商已经创建了解决方案。基本设计是将传入数据限制在一个套接字上的一个内核上的一个线程,然后让该线程将数据分发给所有其他感兴趣的线程,最好使用基于共享内存和无锁数据结构的用户空间代码。

示例是 TIBCO 的 Rendezvous 和 29 West 的 Ultra Messaging,显示 660ns IPC 总线:

http://www.globenewswire.com/newsroom/news.html?d=194703

【讨论】:

  • 嗨,史蒂夫,有什么开源解决方案可以解决这个问题吗?
  • @bdubey 查看aerondisruptor
猜你喜欢
  • 2015-08-23
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多