Workerman 跑稳百万级并发需同步调优 Linux 内核:net.core.somaxconn 与 tcp_max_syn_backlog 必须同设为 65535,fs.file-max 设为 2097152,ulimit -n 与 Worker::$defaultListenBacklog 均匹配该值,并启用 event 扩展确保 epoll 生效,同时开启 tcp_tw_reuse、关闭已弃用的 tcp_tw_recycle。

Workerman 要跑稳百万级并发,光靠堆 Worker 进程没用——90% 的瓶颈卡在 Linux 内核默认参数上。
net.core.somaxconn 和 tcp_max_syn_backlog 必须同步调到 65535
这两个值不一致,高并发下新连接会直接被内核丢弃,现象是客户端偶发 Connection refused 或超时。Webman/Workerman 的 listen 配置里即使写了 ?backlog=65535,也得先让内核允许挂起这么多连接。
- 临时生效:
sudo sysctl -w net.core.somaxconn=65535、sudo sysctl -w net.ipv4.tcp_max_syn_backlog=65535 - 永久生效:写入
/etc/sysctl.d/99-tuning.conf(比/etc/sysctl.conf更推荐),再执行sudo sysctl -p /etc/sysctl.d/99-tuning.conf - 验证是否生效:
sysctl net.core.somaxconn输出必须是65535,不是128或4096 - 别漏掉应用层:在 Webman 的
start.php中显式设Worker::$defaultListenBacklog = 65535
fs.file-max 和 ulimit -n 必须匹配且足够大
一个 TCP 连接 ≈ 1 个文件描述符。百万连接至少要预留 120 万以上句柄空间,否则压测中途就会报 Too many open files,Worker 进程直接退出。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 系统级上限:
fs.file-max = 2097152(写进/etc/sysctl.d/99-tuning.conf) - 用户级限制:
/etc/security/limits.conf加两行:* soft nofile 1048576* hard nofile 1048576 - 注意:改完
limits.conf后,必须用新 shell 登录或重启服务才能生效,ulimit -n当前会话里看到的才是真实值 - 如果用 systemd 启动 Webman,还要在 service 文件里加
LimitNOFILE=1048576
tcp_tw_reuse 和 tcp_max_tw_buckets 要开但别乱开 tcp_tw_recycle
短连接压测时,TIME_WAIT 堆积会导致端口耗尽、新建连接失败。启用 tcp_tw_reuse 是安全的加速手段;而 tcp_tw_recycle 在 NAT 环境下会引发连接异常,2026 年已明确弃用。
- 必须开启:
net.ipv4.tcp_tw_reuse = 1 - 必须扩大桶容量:
net.ipv4.tcp_max_tw_buckets = 262144(避免内核强制回收导致 RST) - 必须关闭:
net.ipv4.tcp_tw_recycle = 0(很多教程还写 1,这是错的) - 补充一招:
net.ipv4.ip_local_port_range = 1024 65535,单 IP 可用端口从默认约 28K 扩到 64K
event 扩展不启用,epoll 就不会真正生效
Workerman 默认 fallback 到 select,连接数过 5000 就开始掉性能。不装 event 扩展,所有内核调优都白搭。
- Debian/Ubuntu:
sudo apt install php-event;CentOS:sudo yum install php-pecl-event - 确认
php.ini有extension=event.so,然后重启 PHP 进程 - 验证:
php --ri event输出中必须含backend => epoll,不是select或空 - 压测对比:用
ab -c 5000测,未启用时大概率报apr_pollset_poll: The timeout specified has expired,启用后消失
真正难的不是改哪几行参数,而是改完之后必须逐项验证——比如 sysctl 显示值对了,ulimit -n 却还是 1024,或者 event 扩展加载了但 backend 显示 kqueue(说明跑在 macOS 上)。这些细节不卡住,百万并发永远只是理论数字。

















