现场是这样的。一台 4 核 8G 的 CentOS 7.9 跑 PHP-FPM,每天中午高峰 error.log 就刷 listen queue of socket full 的告警,紧接着 nginx 出现五零二,过了高峰又自己恢复。

中间走过弯路,把「worker 数偏少,单个请求又慢,队列填得比排空快」当成主因,改完现象没变。

这类报错背后常见的原因有几处,逐个排除就行。监听队列长度默认只有 511,worker 全忙时新连接进来没地方排就被丢掉;队列上限还要看内核的 somaxconn,配置写得再大也超不过这个值折半;unix socket 与 tcp 两种监听方式队列表现不同,调参的地方也不一样。

第一件事是看当前队列上限和监听方式

grep -E '^listen' /etc/php-fpm.d/www.conf

接着观察队列有没有溢出记录

ss -lxn | grep -E 'php-fpm|9000'

同时抬高内核与 pool 两处上限

sysctl -w net.core.somaxconn=2048 && sed -i 's/^;*listen.backlog.*/listen.backlog = 2048/' /etc/php-fpm.d/www.conf && systemctl reload php-fpm

剩下的就是确认内核参数已生效

sysctl net.core.somaxconn && grep listen.backlog /etc/php-fpm.d/www.conf

怎么算真的好了,看的是同一批现象。高峰时段 error.log 不再出现 queue full,ss 里 Recv-Q 长时间为 0,五零二比例回落到千分之一以内。

加队列只是缓解,worker 不够还得加进程或优化慢请求;队列越长,雪崩时积压的请求越多。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189