我构建了一个简单的测试程序,每 250 毫秒发送 100 个 UDP 数据包,每个数据包大小为 1000 字节。我发现两个单独的 linux 盒子正在丢弃其中一些数据包。
我的期望是,当我写入 100 个 UDP 数据包时,内核缓冲区能够保留所有这些数据包。 netstat -us
表示丢弃的每个数据包都有RcvbufErrors
。因此,内核接收缓冲区似乎溢出了。但我不明白为什么。
/proc/sys/net/core/rmem_default
显示的值为 212992,因此我认为增加它会有所帮助,因为它已经大于此测试发送的 100kB 批次。
我进行了第二次测试,每 10 毫秒发送 50 个 UDP 数据包,每个数据包大小为 1000 字节。我发现在此测试中没有丢弃任何数据包。这对我来说表明 100kB 溢出缓冲区,而 50kB 不会。它还进一步表明我没有CPU限制或数据包限制 - 此测试发送数据包的速度比第一个快很多倍。
我使用的两台Linux机器:Macbook上的virtualbox和AWS m5a.xlarge
。
我的测试程序:https://github.com/theicfire/rando/tree/master/udp-fail-batch-stack-overflow
您就在缓冲区大小的边缘,尽管看起来不像。
rmem_default
的值并不意味着有那么多字节可供使用。我在阅读用于设置SO_RECVBUF
的手册页时得到了提示:
The kernel doubles this value (to allow space for bookkeeping
overhead) when it is set using setsockopt(2), and this doubled
value is returned by getsockopt(2).
这意味着内核占用了此缓冲区的某些部分。也许是相当大的数量(即它可能用完了rmem_default
设置的一半。
将SO_RCVBUF
选项设置为 125,000 可阻止数据包丢弃。将其设置为 100,000(由于数据包标头,比您发送的数据包批次少一点(会导致数据包被丢弃。即使getsockopt的结果分别是250,000和200,000。