Linux 多播中排队/缓冲延迟的可能位置在哪里?
Posted
技术标签:
【中文标题】Linux 多播中排队/缓冲延迟的可能位置在哪里?【英文标题】:Where are possible locations of queueing/buffering delays in Linux multicast? 【发布时间】:2011-01-18 02:44:43 【问题描述】:我们在 LAN 上的许多 Linux 服务器上大量使用多播消息传递。我们看到很多延误。我们基本上会发送大量的小包裹。我们更关心延迟而不是吞吐量。这些机器都是现代的多核机器(如果算上超线程,至少有 4 个,通常是 8 个,16 个)机器,负载总是 2.0 或更低,通常负载小于 1.0。网络硬件的容量也不足 50%。
我们看到的延迟看起来像排队延迟:数据包的延迟会迅速增加,直到看起来像堵塞,然后恢复正常。
消息结构基本上是这样的:在“发送线程”中,从队列中拉出消息,添加时间戳(使用gettimeofday()
),然后调用send()
。接收程序接收消息,为接收时间加上时间戳,并将其推送到队列中。在一个单独的线程中,处理队列,分析发送和接收时间戳之间的差异。 (请注意,我们的内部队列不是问题的一部分,因为时间戳是在我们的内部队列之外添加的。)
我们真的不知道从哪里开始寻找这个问题的答案。我们不熟悉 Linux 内部结构。我们的怀疑是内核在发送端或接收端(或两者)对数据包进行排队或缓冲。但我们不知道如何追踪它。
不管怎样,我们使用的是 CentOS 4.x(RHEL 内核 2.6.9)。
【问题讨论】:
从做wireshark跟踪开始,这样你就会看到排队是因为网络设备,还是丢包(即使是简单的交换机也疯狂排队,通常是丢包的主要来源) 我们绝对不会丢包,因为我们对所有内部消息进行排序并检查丢包。运行像 Wireshark 这样的东西是侵入性的,不适合生产环境。我们无法在测试环境中复制这些延迟。因此,我们希望从逻辑上理解 Linux 内核在多播发送和接收方面的行为。 另外,我还要补充一点,在某些情况下,发送者和接收者在同一台机器上。在这种情况下,我们仍然会看到这些延迟效应。这样就解决了问题的网络硬件部分。 【参考方案1】:这是一个很好的问题。在 CentOS 上,像大多数 *nix 风格一样,每个多播套接字都有一个 UDP 接收/发送缓冲区。此缓冲区的大小由 sysctl.conf 控制,您可以通过调用 /sbin/sysctl -a 查看缓冲区的大小
以下项目显示了我的默认和最大 udp 接收大小(以字节为单位)。这些数字越大,如果您的应用程序消耗数据的速度太慢,网络/内核可能会引入更多的缓冲和延迟。如果您对数据丢失建立了良好的容忍度,则可以使这些缓冲区非常小,并且您将看不到上述延迟的增加和恢复。权衡是缓冲区溢出时数据丢失 - 您可能已经看到了。
[~]$ /sbin/sysctl -a |内存 net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216
在大多数情况下,您需要将 default = 设置为您的最大值,除非您在创建套接字时控制它。
您可以做的最后一件事(取决于您的内核版本)是查看您的进程或至少整个框的 PID 的 UDP 统计信息。
cat /proc/net/snmp | grep -i udp Udp:InDatagrams NoPorts InErrors OutDatagrams udp:81658157063 145 616548928 3896986
cat /proc/PID/net/snmp | grep -i udp Udp:InDatagrams NoPorts InErrors OutDatagrams udp:81658157063 145 616548928 3896986
如果从我的帖子中不清楚,延迟是由于您的应用程序没有足够快地消耗数据并迫使内核缓冲上述结构中的流量。网络、内核,甚至你的网卡环形缓冲区都可以在延迟方面发挥作用,但所有这些项目通常只会增加几毫秒。
让我知道您的想法,我可以为您提供更多信息,让您了解如何在应用中查看以提高性能。
【讨论】:
所以说在发送端没有内核缓冲是否公平?在接收端,没有内核缓冲,除非数据消耗得不够快?不幸的是,我没有每个 PID 的 UDP 统计信息(我不确定我的 2.6.9-78.ELlargesmp 内核是否不够新,或者根本没有为此配置)。无论如何,我绝对对任何有关从我们的应用程序中获得更多性能的信息感兴趣。另请注意,我们实际上关心的是“只有几毫秒”——这实际上是一个实时应用程序。谢谢! 您的总结几乎 100% 符合我对 linux 中的多播堆栈的理解。唯一的区别是,无论您在另一端消费数据的速度有多快,“发送”端都可能发生排队。发送端排队是网速不足、网卡质量差、一般性能问题(负载、内存等)的结果。发送端排队不是很常见。是的,这一切都在毫秒或更多的范围内。 还有一点,如果您的网卡在发送端使用 intel e1000 驱动程序,由于驱动程序处理硬件中断的方式,您会看到 0.1 毫秒的延迟突发。【参考方案2】:数据包可以在发送和接收端内核、NIC 和网络基础设施中排队。您会发现大量可以测试和调整的项目。
对于 NIC,您通常可以找到中断合并参数 - NIC 在通知内核或在等待批处理数据包时发送到线路之前将等待多长时间。
对于 Linux,您有发送和接收“缓冲区”,它们越大,您就越有可能在批处理操作中处理数据包时遇到更高的延迟。
对于架构和 Linux 版本,您必须了解上下文切换的成本以及是否启用了锁或抢先调度。考虑最小化运行的应用程序数量,使用进程关联性将进程锁定到特定内核。
不要忘记计时,您使用的 Linux 内核版本在 gettimeofday()
时钟 (2-4ms) 上的精度非常差,而且调用成本非常高。考虑使用替代方案,例如从核心 TSC 或外部 HPET 设备读取数据。
英特尔的图表: alt text http://www.theinquirer.net/IMG/142/96142/latency-580x358.png?1272514422
【讨论】:
【参考方案3】:如果您决定需要在生产环境中捕获数据包,则可能值得考虑使用交换机上的监控端口并使用非生产机器捕获数据包。这还可以让您在传输路径上的多个点捕获数据包并比较您所看到的。
【讨论】:
另外考虑使用 TS-Associates TipOff 等专用硬件设备的众多咨询公司或监控专家之一:ts-associates.com/view/tipoff以上是关于Linux 多播中排队/缓冲延迟的可能位置在哪里?的主要内容,如果未能解决你的问题,请参考以下文章