Linux 有一个tcp_mem
设置,用于设置分配给所有正在运行的应用程序的 TCP 连接的内存量。根据官方文档:
tcp_mem - 3 个整数的向量:最小值、压力、最大值 最小值:低于此页数的 TCP 不会关心其内存需求。
压力:当 TCP 分配的内存量超出此页数时,TCP 会缓和其内存消耗并进入内存压力模式,当内存消耗降至“最小值”以下时退出该模式。
最大值:所有 TCP 套接字允许排队的页面数。
默认值是在启动时根据可用内存量计算的。
我们看到一个应用程序在 Prod 中突破了此阈值,并且其dmesg
日志包含如下一行:TCP: out of memory -- consider tuning tcp_mem
。
由于某种原因,我无法在本地重新运行同一个应用程序。因此,我想编写另一个简单的应用程序来在本地重现此错误。
到目前为止,我已经尝试过:
- 大型网络下载(使用 NodeJS 对预签名的 S3 URL 进行 HTTP GET 和使用 Python 的 Boto3 SDK 的 S3-Get-Objects)。
- Python 的套接字库在 TCP 上进行客户端-服务器传输(同时关闭/不关闭客户端套接字)。
在所有情况下,我都能达到tcp_mem
上限但不会超出。然而,我发现 Prod 应用程序明显超出了上限(例如,6000 对 4400)。
那么,问题是:我可以尝试tcp_mem
在本地重现哪些突破限制的情况?
答案1
我认为超出tcp_mem
限制是其他问题的结果。TCP 层内存消耗过高可能是由于丢失 TCP 段造成的。在重新传输丢失的段之前,TCP 堆栈会存储其他接收到的数据。只有在收到所有丢失的数据后,您的应用程序才能处理这些数据。
因此,如果您想模拟该tcp_mem
问题,您可以删除 tcp 连接的随机段。但我认为这对您没有帮助。最好尝试解决问题的根源。检查输出nstat
,尤其是 tcp 丢失段和 tcp 重传计数器。捕获流量并在 wireshark 中分析它。