![Linux下判断一个socket消耗多少内存的公式是什么?](https://linux22.com/image/43052/Linux%E4%B8%8B%E5%88%A4%E6%96%AD%E4%B8%80%E4%B8%AAsocket%E6%B6%88%E8%80%97%E5%A4%9A%E5%B0%91%E5%86%85%E5%AD%98%E7%9A%84%E5%85%AC%E5%BC%8F%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
我正在做一些容量规划,我想知道是否有一个公式可以用来预测(从内存的角度)我的服务器可以处理多少个 TCP 连接。目前,我只关心内存要求。
我认为公式中会出现的一些变量是:
- sysctl
net.ipv4.tcp_wmem
(最小值或默认值) - sysctl
net.ipv4.tcp_rmem
(最小值或默认值) - sock、sock_common、proto 和其他每个套接字数据结构的大小。
我不确定实际分配了多少 tcp_wmem 和 tcp_rmem 以及何时分配该内存。在套接字创建时?一经请求?
答案1
tcp_mem 更重要,因为它定义了 tcp 堆栈在内存使用方面的行为方式。 IMO 发送和接收缓冲区应该是 tcp_mem 的倍数。以下是接收缓冲区公式的链接:http://www.acc.umu.se/~maswan/linux-netperf.txt。简而言之:
开销为:window/2^tcp_adv_win_scale(tcp_adv_win_scale 默认值为 2)因此,对于 Linux 接收窗口 (tcp_rmem) 的默认参数:87380 - (87380 / 2^2) = 65536。给定跨大西洋链路(150 ms RTT),最大性能最终为:65536/0.150 = 436906 bytes/s 或大约 400 kbyte/s,这在今天确实很慢。随着默认大小的增加:(873800 - 873800/2^2)/0.150 = 4369000 字节/秒,或大约 4Mbytes/秒,这对于现代网络来说是合理的。请注意,这是默认设置,如果发送方配置了更大的窗口大小,它会很高兴地扩展到 10 倍(8738000*0.75/0.150 = ~40Mbytes/s),这对于现代网络来说非常好。
以下是文章中关于 tcp_mem 的内容:
您删除的是对 TCP 性能的人为限制,如果没有该限制,您将受到可用的端到端带宽和损耗的限制。因此,您最终可能会更有效地使上行链路饱和,但 tcp 擅长处理此问题。
在我看来,较大的中间 tcp_mem 值可以加快连接速度,但安全性会降低,并会稍微增加内存使用量。
您可以使用以下方式监控网络堆栈:
grep skbuff /proc/slabinfo
答案2
如果您可以修改源代码,则使用 rusage 数据来测量 RSS 并记录测量时正在使用的 TCP 连接数。
如果无法更改源代码,则使用top或ps报告的网络应用程序的RSS,并从 中获取测量时的网络连接数lsof -i
。
当您的应用程序经历峰值负载时,每分钟收集一次此数据,并根据该数据您可以得出一个将连接数与 RAM 使用情况联系起来的公式。
当然,还有很多东西可以测量,特别是您可能想要测量内核 RAM 使用情况,尽管 tcp 数据结构应该是可以提前预测和计算的。无论如何,看看这个问题https://serverfault.com/questions/10852/what-limits-the-maximum-number-of-connections-on-a-linux-server有关 TCP 调整以及如何清楚地了解网络堆栈中发生的情况的更多信息。
答案3
大卫对所提出的问题提供了非常好的答案,但是除非您专门使用LFN,那么即使在基于事件的服务器上,TCP 缓冲区也可能只是每个连接占用空间的一小部分。
对于容量规划来说,测试服务器和计算负载内存使用率的回归是无可替代的。