我们在LAN上的许多Linux服务器上大量使用多播消息。我们看到了很多延迟。我们基本上发送了大量的小包裹。我们更关心延迟而不是吞吐量。这些机器都是现代的多核机器(至少四台,如果算上超线程,通常是八台,16台),负载总是在2.0或更低,通常负载小于1.0。网络硬件的容量也低于50%。
我们看到的延迟看起来像排队延迟:数据包将迅速开始增加延迟,直到它们看起来堵塞,然后恢复正常。
消息传递结构基本上是这样的:在“发送线程”中,从队列中拉出消息,添加时间戳(使用gettimeofday()
),然后调用send()
。接收程序接收消息,为接收时间加时间戳,并将其推入队列。在单独的线程中处理队列,分析发送和接收时间戳之间的差异。(请注意,内部队列不是问题的一部分,因为时间戳是在内部队列之外添加的。)
我们真的不知道从哪里开始寻找这个问题的答案。我们不熟悉Linux的内部结构。我们怀疑内核正在发送端或接收端(或两者)排队或缓冲数据包。但我们不知道如何追踪它。
值得注意的是,我们使用的是RHEL 4.x ( CentOS内核2.6.9)。
发布于 2010-03-19 18:45:16
数据包可以在发送和接收端内核、NIC和网络基础设施中排队。你会发现有太多的项目可以测试和调整。
对于NIC,您通常可以找到中断合并参数- NIC在等待批处理数据包时,在通知内核或发送到网络之前将等待多长时间。
对于Linux,你有发送和接收的“缓冲区”,它们越大,你就越有可能遇到更高的延迟,因为数据包是以批处理的方式处理的。
对于架构和Linux版本,您必须知道上下文切换有多昂贵,以及是否启用了锁或抢占式调度。考虑最小化正在运行的应用程序的数量,使用进程关联将进程锁定到特定的核心。
别忘了计时,你正在使用的Linux内核版本在gettimeofday()
时钟(2-4ms)上的精度相当糟糕,而且调用起来相当昂贵。考虑使用替代方案,例如从核心TSC或外部HPET设备读取。
来自英特尔的图表:alt text http://www.theinquirer.net/IMG/142/96142/latency-580x358.png?1272514422
发布于 2010-02-19 22:38:37
这是一个很好的问题。在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统计信息,或者至少查看整个系统的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
如果从我的帖子中看不清楚,延迟是由于您的应用程序没有足够快地消耗数据,并迫使内核在上面的结构中缓冲流量。网络、内核、甚至您的网卡环形缓冲区都会产生延迟,但所有这些项通常只会增加几毫秒。
让我知道你的想法,我可以给你更多的信息,在你的应用程序中寻找更多的性能。
发布于 2010-03-19 18:57:48
如果您决定需要在生产环境中捕获数据包,则可能值得考虑使用交换机上的监视器端口,并使用非生产机器捕获数据包。这还将允许您捕获传输路径上多个点上的数据包,并比较您所看到的内容。
https://stackoverflow.com/questions/2285152
复制相似问题