本质是系统文件描述符耗尽或内核网络栈瓶颈,需先查进程fd限制与占用、再查软中断分布,分层调大ulimit、配置systemd/supervisord、合理设置maxConnections与worker count,并启用reusePort及分散网卡中断亲和性。

Workerman连接数过高导致新连接被拒绝、ESTABLISHED堆积、响应延迟飙升,本质是系统文件描述符耗尽或内核网络栈瓶颈触发的连锁反应,不是单纯调大maxConnections就能解决。
确认真实瓶颈在哪
先查进程实际可用fd上限,别信配置文件:用cat /proc/$(pgrep -f "start.php" | head -1)/limits | grep "Max open files",输出两列数字——左边是软限制,右边是硬限制。【软限制必须≤硬限制,否则启动时会被截断】
再看当前fd占用:用lsof -p $(pgrep -f "start.php" | head -1) | wc -l,如果接近或等于上一步查出的软限制值,说明确实是fd耗尽;如果远低于该值但连接已卡死,就要查网卡软中断是否单核打满(top看si%是否持续>30%且只集中在CPU0)。
分层调整系统文件描述符限制
方法一:临时生效(仅用于测试或紧急恢复)
在启动Workerman前执行:ulimit -n 65535,然后运行php start.php start -d。这步操作起来很简单,但重启shell后失效。
方法二:永久生效(生产环境必须做)
① 编辑/etc/security/limits.conf,追加两行:www-data soft nofile 65535www-data hard nofile 65535
② 如果用systemd管理,还需编辑/etc/systemd/system/workerman.service,在[Service]段下加LimitNOFILE=65535。
【改完必须重启Workerman主进程,reload不生效,因为fd限制只在fork时读取一次】
方法三:绕过PAM限制(supervisord或crontab启动时必做)
supervisord配置中不能只写command=php start.php start -d,要改成:command=/bin/sh -c "ulimit -n 65535 && php start.php start -d"。
收紧Workerman自身连接控制
设$worker->maxConnections为系统可用fd的70%~80%,例如cat /proc/$(pgrep -f "start.php"|head -1)/limits | awk '{print $5}' | head -1查出硬限制是65535,则设$worker->maxConnections = 52428。【不要设成65535——定时器、日志句柄、DNS查询也要占fd,留余量才能稳住】
同时检查$worker->count是否合理:用nproc查CPU核心数,设为1.5倍左右。4核机器设6个进程,16核设24个,再多反而因调度开销拖慢吞吐。
启用$worker->reusePort = true,让内核直接把新连接均匀分发到各Worker进程,避免默认队列竞争导致的分配倾斜。
释放网卡软中断压力
第一步:确认网卡是否支持多队列,执行ethtool -l eth0(把eth0换成你的网卡名),看Combined最大值是否>1。
第二步:查当前中断分布,执行cat /proc/interrupts | grep eth0,观察每行末尾各CPU计数是否严重不均。
第三步:手动绑定中断到多个CPU,例如将IRQ 45绑定到CPU0-3:echo 0-3 > /proc/irq/45/smp_affinity_list(需root权限)。绑定前先停掉irqbalance服务,避免它动态抢改。
第四步:压测验证,运行watch -n1 'cat /proc/interrupts | grep eth0',看到各CPU列计数逐步趋近均匀,说明软中断负载已分散。

















