centos 上 php-fpm 占用太多状态为 CLOSED 的 socket 且不释放, 如何解决?

发布于 2022-09-11 17:56:59 字数 2913 浏览 15 评论 0

[temp@xigua ~]$ ss -s 
Total: 83678 (kernel 0)
TCP:   84982 (estab 127, closed 84812, orphaned 0, synrecv 0, timewait 1485/0), ports 0

Transport Total     IP        IPv6
*         0         -         -        
RAW       0         0         0        
UDP       4         3         1        
TCP       170       168       2        
INET      174       171       3        
FRAG      0         0         0


这里可以看到 CLOSED 状态的socket 有8w+ (closed 84812), 同时查看某个 fpm :

[temp@xigua ~]$ ss -s $ lsof -p ${fpm-pid}|grep 'protocol: TCP'|wc -l   
1043

fpm 进程一共有 8 0个, 所以几乎可以肯定全是 fpm 导致的上述占用过多 CLOSED socket, 主要是我不理解为啥 fpm
不释放这些 socket, CLOSED 状态下的 socket 不是应该转瞬就被系统回收了吗?
这些状态为 CLOSED 的 socket 仍然占用较多内存, 当超过 tcp 上限(cat /proc/sys/net/ipv4/tcp_mem)的时候会报错 : out of memory -- consider tuning tcp_mem
请问我需要怎么进一步解决呢?


P.S. 2019年2月26日17:53:34 进一步的信息补充 :

$ ls -l /proc/${pfm}/fd|wc -l
1059

检查 sockstat :

cat /proc/net/sockstat 
sockets: used 84442
TCP: inuse 168 orphan 0 tw 3052 alloc 84262 mem 84093
UDP: inuse 3 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0


$ netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n

  1 established)
  1 Foreign
  8 LISTEN
 28 CLOSE_WAIT
138 ESTABLISHED
782 TIME_WAIT

    
    

fpm 的配置 :

pm.max_children = 80
pm.max_requests = 100000

某次重启前

$ cat /proc/net/sockstat
sockets: used 29901
TCP: inuse 168 orphan 0 tw 3618 alloc 29720 mem 29563
UDP: inuse 3 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0

$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7821         824         250         418        6746        6064
Swap:           511          98         413

重启后

$ cat /proc/net/sockstat  
sockets: used 387
TCP: inuse 167 orphan 0 tw 3504 alloc 207 mem 42
UDP: inuse 3 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0   

 
 
$ lsof -p ${fpm-pid}|less     
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php-fpm 17699 temp 71u sock 0,7 0t0 552415632 protocol: TCP
php-fpm 17699 temp 72u sock 0,7 0t0 552428529 protocol: TCP
php-fpm 17699 temp 73u sock 0,7 0t0 552450479 protocol: TCP
php-fpm 17699 temp 74u sock 0,7 0t0 552462900 protocol: TCP
php-fpm 17699 temp 75u sock 0,7 0t0 552523600 protocol: TCP
php-fpm 17699 temp 76u sock 0,7 0t0 552542925 protocol: TCP
php-fpm 17699 temp 77u sock 0,7 0t0 552613133 protocol: TCP
php-fpm 17699 temp 78u sock 0,7 0t0 552639299 protocol: TCP
php-fpm 17699 temp 79u sock 0,7 0t0 552646395 protocol: TCP
php-fpm 17699 temp 80u sock 0,7 0t0 552659030 protocol: TCP
    

发现大量的 "protocol: TCP" 字样, 请教大家这是什么意思?为何不展示出 tcp 连接的双端ip, 端口信息而是省略成了"TCP"字样?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不必你懂 2022-09-18 17:56:59

会不会是php-fpm配置了静态模式?在配置pm = static的情况下php-fpm不会释放进程的。

玩物 2022-09-18 17:56:59

你好,这个问题定位了吗?我这也出现相同的问题,目前也没有分析的思路

陌伤ぢ 2022-09-18 17:56:59

你好,本人也遇到此类处于closed状态的socket没有被释放问题,请问你这个问题解决了吗?解决的思路是什么呢?

初心 2022-09-18 17:56:59

能否提供更多信息, 例如

  1. fpm 进程的最大文件数. cat /proc/$(pidof fpm)/limits
  2. CLOSED 状态 socket 的客户端和服务器地址信息. lsof -n -p $(pidof fpm)
  3. php 应用是否含有 sockets 类操作, 如有, 贴出相关服务的地址.
  4. 在不重启 fpm 进程情况下, CLOSED 状态的连接是否一直存在, 是否由 TIMEWAIT 进入该状态.
  5. 重启 fpm 的初始阶段, 是否 TIMEWAIT 数量大于 CLOSED 数量.
  6. 内核参数. sysctl -a | grep tcp

感觉需要优化 TCP .


根据题主提供的最新信息

cat /proc/net/sockstat 
sockets: used 84442
TCP: inuse 168 orphan 0 tw 3052 alloc 84262 mem 84093
UDP: inuse 3 mem 1
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
$ netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n

  1 established)
  1 Foreign
  8 LISTEN
 28 CLOSE_WAIT
138 ESTABLISHED
782 TIME_WAIT

我很肯定这是 tcp 优化问题, 这种情况通常出现在高负载的服务器, 即 tcp 创建速度(用户态)远高于销毁速度(内核).
你需要酌情调整如下内核参数

net.ipv4.ip_local_port_range
net.ipv4.tcp_fin_timeout
net.ipv4.tcp_tw_reuse
游魂 2022-09-18 17:56:59

closed状态应该是关闭了,从你的说法估计是说socket已经关闭,但是协议栈被没有释放资源?
你用ls -l /proc/fpm进程ID/fd|wc -l 看看

安静 2022-09-18 17:56:59

你这个php-fpm 存在多个进程共享同一个socket的情况么?

closed没关闭,我能想到的就是内核sock->refcnt不为0,所以不会释放

cat /proc/net/tcp | awk '{print $11}' 可以看下tcp socket的引用计数

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文