如何调优 TCP Socket 缓冲区

原文:https://access.redhat.com/solutions/369563

环境

  • Red Hat Enterprise Linux (RHEL)

问题

  • 看到由于套接字缓冲区溢出导致的数据包丢失。
  • netstat -s 报告由于套接字缓冲区过低导致的数据包丢失。

解决方案

如果应用程序未使用 setsockopt 调用来设置其缓冲区大小,则将使用系统默认大小。

  • 默认的 TCP 套接字缓冲区大小由以下文件设置:
$ cat /proc/sys/net/ipv4/tcp_rmem 
4096    87380   4194304
$ cat /proc/sys/net/ipv4/tcp_wmem 
4096    16384   4194304
  • TCP 套接字缓冲区是一个灵活的缓冲区,用于在内核级别处理进出数据包。它会根据当前负载动态调整大小。上述文件中的三个数字表示缓冲区的最小值、默认值和最大值。
  • 可以通过在 /etc/sysctl.conf 文件中添加参数来更改这些值:
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 87380 4194304

对于内存充足且使用 1GB 或 10GB 网卡的机器,如果发生缓冲区裁剪,可以将最大值增加到 16MB。建议在将系统投入生产前,在类似负载下测试这些值。

net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
  • 这些更改需要通过运行以下命令生效:
# sysctl -p
  • 注意不要将缓冲区设置得过大。设置过大可能会对性能产生负面影响。这些缓冲区使用的是系统的物理内存。也就是说,每个 TCP 连接都会占用相应大小的内存。如果缓冲区设置过大,且连接数很多,可能会导致内存不足。此外,每次读写缓冲区时,都会读取整个套接字。这意味着,如果缓冲区大于典型数据包大小,即使实际数据量较小,应用程序也会读取整个缓冲区,从而带来额外开销。
  • 有关增加套接字缓冲区大小可能带来的影响,请参阅文章:更改套接字缓冲区大小的影响是什么?

对于通过调用 setsockopt(SO_RCVBUF) 自行设置缓冲区大小的应用程序:

如果上述 sysctl 内存设置未能显著提高吞吐量,建议增加 setsockopt(SO_RCVBUF) 的调用值,或从应用程序代码中移除该调用。移除该调用将允许内核自动调优内存值。

  • 还需注意,当使用 setsockopt(SO_RCVBUF) 时,应用程序设置的缓冲区大小将受到 net.core.rmem_defaultnet.core.rmem_max 的限制。例如,如果应用程序设置了 1MB 的缓冲区,但 net.core.rmem_max 仅为 256KB,则实际套接字缓冲区将被限制为 256KB。
SO_RCVBUF
              设置或获取套接字接收缓冲区的最大字节数。内核在通过 setsockopt(2) 设置时会将该值翻倍(以留出簿记开销),
              getsockopt(2) 返回的是翻倍后的值。默认值由 /proc/sys/net/core/rmem_default 文件设置,
              最大值由 /proc/sys/net/core/rmem_max 文件设置。该选项的最小值(翻倍后)为 256。

诊断步骤

  • 可以通过查看 netstat -s 的输出来检查套接字缓冲区是否超载:
$ netstat -s | grep socket
    1617 packets pruned from receive queue because of socket buffer overrun
    798 TCP sockets finished time wait in fast timer
    29 delayed acks further delayed because of locked socket
    346941 packets collapsed in receive queue due to low socket buffer
  • 如果有数据包被“裁剪”或“折叠”,则可能需要进行调优。
  • 请注意,在活动较少的服务器上,可能看不到负载或内存压力的明显变化。
    这些 sysctl 更改在连接数达到数千的繁忙服务器上影响更明显。
    应相应进行测试。
更改前(非繁忙服务器)
10:00:01 AM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
10:50:01 AM    611988  15515156     96.21      1368   8560820  10050932     62.30   8101972   6045188      4604
11:00:01 AM    224920  15902224     98.61      1284   8917416  10182208     63.11   8204204   6331076      4952

更改后(非繁忙服务器)
10:00:01 AM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
10:53:39 AM    752268  15374876     95.34      1168   8388744  10207324     63.26   8826552   5067064       768
10:53:40 AM    752832  15374312     95.33      1168   8388744  10206940     63.26   8826848   5067064       768
10:53:41 AM    752052  15375092     95.34      1168   8388744  10207068     63.26   8827452   5067064       880
posted @ 2025-09-08 19:25  LoftyAmbition  阅读(82)  评论(0)    收藏  举报