我正在测试我的代码在一个便宜的数字海洋水滴(2 2GB的内存,但我也尝试添加4 2GB的交换空间,它没有改变任何东西)。
我的程序的一部分有许多UDP客户端DGRAM套接字打开到各种本地端口(从/到127.0.0.1)。
有时,在没有发送大量数据的情况下,send()
调用会失败并返回No buffer space available
(错误105)。
然后,我的程序尝试使用所有其他可用套接字(对于其他本地端口),但它们都同时失败。
我将/proc/sys/net/core/wmem_max
(和/proc/sys/net/core/rmem_max
)设置为16MB,每个套接字的setsockopt SOL_SOCKET, SO_SNDBUF
都设置为8MB。这些都不会改变任何事情。
使用No buffer space available
时,send()
怎么会失败?这不是应该只在我们发送()太快的时候发生吗?但这里是本地的,我不会发送太多数据。
最让我困惑的是,当进程重试任何其他套接字时,它会得到相同的错误。套接字缓冲区不是应该是完全独立的吗?
可能的原因是什么?
发布于 2020-12-13 21:45:43
错误No buffer space available
并不意味着套接字缓冲区已满。这意味着linux内核不能为套接字缓冲区分配内存。没有任何套接字缓冲区的内存,所以当这种情况发生时,在释放一些内存之前,不可能通过任何套接字发送任何数据。增加wmem_max
和rmem_max
可能会使问题变得更糟,因为它们可能会增加每个插槽的内存消耗。您可以检查总体内存消耗以及为udp套接字缓冲区分配了多少内存:
$ cat /proc/net/sockstat
sockets: used 315
TCP: inuse 8 orphan 0 tw 0 alloc 13 mem 1
UDP: inuse 3853 mem 240812
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
本例中的UDP套接字每4KB使用240812页,约为940MB。有3853个打开的插座
$ free -h
total used free shared buff/cache available
Mem: 1.9G 1.8G 75M 1.2M 66M 28M
Swap: 0B 0B 0B
本例中的系统具有2 GB的物理内存和非常低的空闲内存。send
函数极有可能失败,并出现错误No buffer space available
。
如果内存实际上被套接字缓冲区消耗,那么添加交换几乎没有什么帮助,因为AFAIK缓冲区不能被交换出去。
您可以尝试使用内存更大的VM。这可能会有所帮助,或者至少可以推迟这个问题。
您还可以审核应用程序并检查套接字是如何使用的。UDP套接字缓冲区的高内存消耗可能是由应用程序中的错误或错误的设计引起的。例如,如果应用程序侦听UDP套接字,并且有数据,但应用程序不读取任何内容,则内核直到进程终止或直到应用程序调用recv
时才释放内存。许多未调用recv
的已打开套接字可能会耗尽内存。
https://stackoverflow.com/questions/65261295
复制相似问题