登录
首页 >  文章 >  php教程

Workerman长连接文件描述符优化方案

时间:2026-05-31 15:59:47 254浏览 收藏

Workerman长连接出现静默失败——新连接卡在三次握手、无报错、无法建立——根本原因并非框架本身“占满”文件描述符,而是系统级fd限制未随启动方式正确生效:你看到的ulimit -n只是当前shell的值,真正起作用的是Workerman主进程启动时继承的limits;必须通过/proc/pid/limits精准核查实际上限,针对systemd、supervisord或手动启动等不同场景显式配置LimitNOFILE或ulimit前缀,并将应用层maxConnections严格设为系统fd上限的70%~80%(预留定时器、日志、Redis等必要开销),最后务必完整stop再start重启进程——reload无效,因为fd限制仅在fork时读取一次。

怎么解决Workerman长连接占满系统文件描述符的问题?

Workerman长连接本身不“占满”fd,真正卡住的是系统级文件描述符限制没同步调高,导致连接数刚到几千就静默失败——新连接进不来、也不报错,只卡在三次握手完成前。

查清楚当前 Workerman 进程实际能用多少 fd

别信 ulimit -n 输出的 shell 限制值,它和 Workerman 进程无关。唯一可信的是运行中主进程的 limits:

  • 先用 ps aux | grep start.php 找出主进程 pid(通常是第一个 php 进程)
  • 执行 cat /proc//limits | grep "Max open files",看输出里 soft 和 hard 两列数值
  • 再用 lsof -p | wc -l 查当前已用 fd 数,对比上限是否逼近

Workerman 启动时 fd 限制不生效的常见原因

改了 /etc/security/limits.conf 却没效果,大概率是启动方式绕过了 PAM 加载流程:

  • systemd 管理的服务:必须在 service 文件里显式加 LimitNOFILE=65535,光改 limits.conf 不管用
  • supervisord 管理:不能只写 command=php start.php start -d,得包一层 shell:command=/bin/sh -c "ulimit -n 65535 && php start.php start -d"
  • crontab 或手动后台启动(nohup php start.php start -d &):同样要带 ulimit -n 前缀,否则继承的是登录 shell 的默认 1024

maxConnections 和系统 fd 的配比关系

$worker->maxConnections 是纯应用层开关,它不会自动适配系统 fd 上限。设太高反而会掩盖问题:

  • 建议把 $worker->maxConnections 设为系统可用 fd 的 70%~80%,比如 cat /proc//limits 显示 Max open files 是 65535,那 $worker->maxConnections = 50000 比较稳妥
  • 留下的余量要覆盖定时器、日志文件、DNS 查询、Redis 连接等其他开销,否则 fd 耗尽后,心跳定时器都可能注册失败
  • 不要盲目设成 65535 —— 即使 fd 允许,内核参数 net.core.somaxconnnet.ipv4.ip_local_port_range 也会成为新瓶颈

最常被忽略的一点:fd 限制只在进程 fork 时读取一次,改完配置必须完整重启 Workerman 进程(stopstart -d),reload 不会重新加载 ulimit。

以上就是本文的全部内容了,是否有顺利帮助你解决问题?若是能给你带来学习上的帮助,请大家多多支持golang学习网!更多关于文章的相关知识,也可关注golang学习网公众号。

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>