IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

网络栈内存不足引发进程挂起问题

系统技术非业余研究 2013-03-11 13:40:08 累计浏览 5,224 次
本机暂存

我们知道TCP socket有发送缓冲区和接收缓冲区,这二个缓冲区都可以透过setsockopt设置SO_SNDBUF,SO_RCVBUF来修改,但是这些值设多大呢?这些值和协议栈的内存控制相关的值什么关系呢?

我们来解释下:

$ sysctl net|grep mem

net.core.wmem_max = 131071

net.core.rmem_max = 131071

net.core.wmem_default = 124928

net.core.rmem_default = 124928

net.core.optmem_max = 20480

net.ipv4.igmp_max_memberships = 20

net.ipv4.tcp_mem = 4631520      6175360 9263040

net.ipv4.tcp_wmem = 4096        16384   4194304

net.ipv4.tcp_rmem = 4096        87380   4194304

net.ipv4.udp_mem = 4631520      6175360 9263040

net.ipv4.udp_rmem_min = 4096

net.ipv4.udp_wmem_min = 4096

下面的图很好的解释了上面的问题:

socket_mem

这里要记住的是:TCP协议栈内存是不可交换物理内存,用一字节少一字节。

也正是由于这一点,操作系统出厂的时候上面的默认的内存设置都不算太大。对于一个不是网络密集型的服务器问题不大,但是对于如承担C1M链接的服务器来讲,问题就来了。我们在实践中会发现tcp服务经常超时,有时候超过100ms. 那么这个问题如何定位呢?

我们知道当协议栈缺少内存的时候会调用sk_stream_wait_memory等待其他进程释放出内存,所以这个函数的等待时间就是我们的进程被阻塞的时间。

下面我们来验证下:

$ cat /usr/share/doc/systemtap-1.6/examples/network/sk_stream_wait_memory.stp
#!/usr/bin/stap
# Simple probe to detect when a process is waiting for more socket send
# buffer memory. Usually means the process is doing writes larger than the
# socket send buffer size or there is a slow receiver at the other side.
# Increasing the socket's send buffer size might help decrease application
# latencies, but it might also make it worse, so buyer beware.
#
# Typical output: timestamp in microseconds: procname(pid) event
#
# 1218230114875167: python(17631) blocked on full send buffer
# 1218230114876196: python(17631) recovered from full send buffer
# 1218230114876271: python(17631) blocked on full send buffer
# 1218230114876479: python(17631) recovered from full send buffer
  
probe kernel.function("sk_stream_wait_memory")
{
        printf("%u: %s(%d) blocked on full send buffer\n",
                gettimeofday_us(), execname(), pid())
}
  
probe kernel.function("sk_stream_wait_memory").return
{
        printf("%u: %s(%d) recovered from full send buffer\n",
                gettimeofday_us(), execname(), pid())
}
$ sudo stap sk_stream_wait_memory.stp  
1218230114875167: python(17631) blocked on full send buffer
1218230114876196: python(17631) recovered from full send buffer
1218230114876271: python(17631) blocked on full send buffer
1218230114876479: python(17631) recovered from full send buffer

如果我们观察到了进程由于缺少内存被阻塞,那么是时候调整协议栈的内存限制了。

小结:网络很复杂,需要定量分析!

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. Java开发岗位面试题归类汇总 (累计阅读 22,157)
  2. Linux内存点滴 用户进程内存空间 (累计阅读 13,232)
  3. Linux Used内存到底哪里去了? (累计阅读 11,868)
  4. Linux操作系统的内存使用方法详细解析 (累计阅读 10,151)
  5. 几个内存相关面试题(c/c++) (累计阅读 9,447)
  6. top 命令补充 ( VIRT RES SHR) (累计阅读 9,117)
  7. Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (累计阅读 7,721)
  8. redis 运维实际经验纪录之一 (累计阅读 7,713)
  9. 必看!linux系统如何查看内存使用情况 (累计阅读 7,170)
  10. Linux操作系统中内存buffer和cache的区别 (累计阅读 6,475)