我们在 LAN 上的许多 Linux 服务器上大量使用多播消息传递。我们看到很多延误。我们基本上发送大量的小包裹。我们更关心延迟而不是吞吐量。这些机器都是现代的多核(至少四核,一般是八核,如果算上超线程则为 16 个)机器,负载始终为 2.0 或更低,通常负载小于 1.0。网络硬件的容量也低于 50%。
我们看到的延迟看起来像排队延迟:数据包的延迟将很快开始增加,直到看起来堵塞,然后恢复正常。
消息结构基本上是这样的:在“发送线程”中,从队列中提取消息,添加时间戳(使用 gettimeofday()
),然后调用 send()
。接收程序接收消息,为接收时间加上时间戳,并将其插入队列。在单独的线程中,处理队列,分析发送和接收时间戳之间的差异。 (请注意,我们的内部队列不是问题的一部分,因为时间戳是在我们的内部队列之外添加的。)
我们真的不知道从哪里开始寻找这个问题的答案。我们对 Linux 的内部结构并不熟悉。我们怀疑内核正在对数据包进行排队或缓冲,无论是在发送端还是接收端(或两者)。但我们不知道如何追踪和追踪它。
就其值(value)而言,我们使用的是 CentOS 4.x(RHEL 内核 2.6.9)。
最佳答案
这是一个很好的问题。在 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 统计信息,或者至少查看整个盒子。
猫/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
如果我的帖子还不清楚,那么延迟是由于您的应用程序消耗数据的速度不够快,并迫使内核在上述结构中缓冲流量。网络、内核,甚至网卡环形缓冲区都会增加延迟,但所有这些项目通常只会增加几毫秒。
请告诉我您的想法,我可以为您提供更多信息,告诉您在应用程序中应注意哪些方面以提高性能。
关于linux - Linux 多播中队列/缓冲延迟的可能位置在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2285152/