$worker->count=8后吞吐下降主因是未启用reuseport导致accept单点瓶颈,需设$worker->reuseport=true、监听0.0.0.0、调优somaxconn及分散网卡中断亲和性。

Workerman TCP 高并发不是靠堆进程数硬扛,而是要让每个连接真正“不卡住”——从内核收包、进程分发、事件循环到业务处理,整条链路都不能有单点阻塞。
为什么 $worker->count = 8 后吞吐反而下降?
多进程不是越多越好。Workerman 主进程监听端口后,用 accept() 把新连接分发给子进程;但如果没启用 reusePort,所有 SYN 包都得排队等主进程调用 accept(),而这个操作默认只能由一个 CPU 核处理,变成软中断瓶颈。
- 现象:top 里
si%持续 >40%,且集中在单个 CPU;ss -s显示recv-q不断上涨 - 必须加:
$worker->reusePort = true;(注意:PHP ≥ 7.2 且 Linux ≥ 3.9) - 同时确保监听地址是
tcp://0.0.0.0:xxxx,不是127.0.0.1——后者直接废掉多核并行能力 -
$worker->count建议设为 CPU 物理核心数(非超线程数),压测后再微调;超过 8 通常收益递减
连接建立阶段就超时(Connection timed out)怎么定位?
这不是 PHP 代码问题,是连接根本没进到 Workerman。高并发下最常见三个断点:
- 本地端口耗尽:
net.ipv4.ip_local_port_range默认只有 32768–65535,短连接密集时快速占满;改宽:`sysctl -w net.ipv4.ip_local_port_range="1024 65535"` - SYN 队列溢出:内核参数
net.core.somaxconn默认常为 128,远不够;应设为 `65535` 并同步调大listen()的 backlog(Workerman 内部已设为 65535,但系统层必须跟上) - 云平台限速:阿里云/腾讯云对单 IP 新建连接数(conn/s)有隐式限制,间歇性超时大概率是它;需提工单申请提升配额,或做客户端连接复用
业务逻辑里哪些写法会让 TCP 连接“假活真堵”?
Workerman 的 onMessage 回调一旦执行同步阻塞操作,整个 Worker 进程的事件循环就停摆,其他连接全部卡住。
- 绝对禁止:
file_get_contents()、sleep()、同步 MySQL 查询(mysqli_query)、curl_exec() - 必须换异步方案:
workerman/mysql客户端、workerman/http-client、AsyncTcpConnection - 耗时任务立刻扔进队列:用 Redis +
php-resque或amqp异步处理,onMessage只负责快速响应 ACK - 心跳别用
ping/pong轮询:改用$connection->getTimer()->add(30, function() { ... })主动检测,避免连接堆积
为什么开了 libevent 还是卡在 10 万连接?
Worker::$globalEvent = 'libevent' 确实能提升单进程事件轮询效率,但它不解决底层资源瓶颈。
- 先检查
ulimit -n:必须 ≥ 连接数 × 2(每个连接至少占 2 个 fd),建议设为1048576 - 确认
opcache.enable=1且opcache.memory_consumption≥ 256M,否则每次请求都重编译脚本 - 禁用所有非必要扩展(如 xdebug、blackfire),它们会让 event loop 延迟显著上升
- 最关键的遗漏项:网卡多队列中断没分散。用
cat /proc/interrupts | grep eth0看 IRQ 是否全落在 CPU0;需手动绑定到多个 CPU,例如:echo 0-3 > /proc/irq/123/smp_affinity_list
真正的瓶颈往往不在 PHP 代码里,而在 /proc/sys/net 的某个参数、网卡驱动的中断亲和性、或者云厂商没明说的连接新建速率限制。调优不是改完配置就完事,而是每改一项,都用 ss -s、cat /proc/interrupts、strace -p [pid] 实时验证效果。











