Supervisor管理swoole进程的坑

环境

  • 系统: CentOS 8.2 64 位
  • 机器:Intel(R) Xeon(R) Platinum 8369HC CPU @ 3.30GHz 4 核 8G
  • PHP :7.4
  • 框架:swoft2.x

发现

系统监控发现机器负载异常的高,如下图所示,从 1 点开始,由不到 1 的负载到后面超 100,负载、内存不断的飙高,但 CPU 使用率却几乎没怎么变化过。

排查

  • 通过 top 命令进行排查

通过 top 命令,看到有大量的 D 状态 swoft 进程。

由于我们采用 supervisor 来管理 swoft 进程,所以先排查 supervisor 是否存在问题。

  • 查看配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[program:prod_cms]
command=/usr/bin/php /mnt/alidata1/haodanku_CMS/bin/swoft http:start
;process_name=%(process_num)02d
autostart=true
autorestart=true
startsecs=1
startretries=10
user=root
stdout_logfile=/data/supervisor/production_cms_swoft_api.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stderr_logfile=/data/supervisor/production_cms_swoft_api_err.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=50
stderr_capture_maxbytes=1MB

由配置知道,进程启动失败时有输出日志信息。

查看错误日志信息,发现存在内存溢出问题。但由于该日志信息无输出时间信息,无法判断是否由此问题引起。

查看启动日志信息,发现启动时存在端口被占用。

  • 查看端口占用情况
1
netstat -anp | grep 18406

发现存在 tcp 连接,但无对应进程。

分析

supervisord 在杀进程时,swoole 子进程事件未处理完毕,主进程就强制杀掉,导致子进程无法收到关闭信号,所以一直没被杀掉,tcp 连接也没有正常关闭。

解决

  • 编辑supervisord配置参数。增加停止等待时间以及杀掉进程时以进程组的形式进行杀掉增加停止等待时间以及杀掉进程时以进程组的形式进行杀掉
1

stopwaitsecs=60
stopasgroup=true
stopwaitsecs=true

1

tips