Webman压测卡在5k QPS主因是连接池未生效、event扩展未被选中、内核参数与worker数量未对齐;需验证database.php中'default'含pool配置、php--ri event显示backend=>epoll、同步调优somaxconn/tcp_max_syn_backlog/netdev_max_backlog。

Webman 压测卡在 5k QPS 上不去?不是框架不行,而是连接池没生效、event 扩展没被选中、内核参数和 worker 数量没对齐——三者缺一不可。
为什么 ab 或 wrk 压测时总卡在 5000 QPS 左右
这不是 Webman 的瓶颈,而是典型配置断层:数据库查询直连、Redis 每次 new 实例、视图里写 Db::table()、没开连接池。这些操作让每个请求都新建 TCP 连接或 PDO 实例,worker 进程很快被阻塞住,QPS 被死死压在 I/O 等待上。
常见现象包括:
-
Too many open files错误频发,ulimit -n未调高 -
ss -s显示TIME_WAIT持续高于 30000 -
ps aux --sort=-%mem发现单个 worker RSS 超过 120MB,但$worker->count却设到了 16 - 日志里反复出现
Connection refused,但 MySQLshow status like 'Threads_connected'只有 80+
根本原因:你把 Webman 当成了 Laravel + RoadRunner 用,却没配异步客户端,也没管连接复用。
如何确认 event 扩展真正生效
装了 php-event 不等于就用了 epoll。Workerman 启动日志里若还显示 Using poll as event loop,说明它根本没选中 event 扩展。
必须做三件事:
- 运行
php --ri event,确认输出含backend => epoll,而不是select或空值 - 检查
php.ini中extension=event.so是否在swoole.so或redis.so之后加载(顺序影响优先级) - 重启 Webman 后,看启动日志是否变成
Using epoll as event loop
如果仍不生效,大概率是 PHP 编译时没带 --with-event,得重装 PHP 或换包管理器安装版本。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
数据库连接池为什么始终不命中
Webman 的连接池只对显式指定连接名的调用起作用。Db::table('user')->get() 默认走的是 'default' 连接,而 config/database.php 里若只写了 'pool' => [...] 顶层键,没把它挂到 'default' 下,就会退化为每次 new PDO。
验证方式很简单:
- 在任意控制器里加
var_dump(Db::connection()->getPdo() === Db::connection()->getPdo()),返回false就说明没复用 - 检查
config/database.php中'default'数组是否包含'pool' => ['min_connections' => 2, 'max_connections' => 32] - 模板里禁止出现任何
Db::或Redis::调用,所有数据必须由控制器查好传入
高频场景如侧栏推荐、标签云,必须统一改用 Db::connection('pool')->table(...)。
Linux 内核参数与 $worker->count 怎么联动调优
worker 数量不是孤立配置,它直接驱动内核网络栈负载。设高了不提速,反而触发丢包、上下文切换飙升、文件描述符耗尽。
必须同步调这三组参数:
-
net.core.somaxconn = 65535(全连接队列),且 Webman 中Worker::$defaultListenBacklog = 65535 -
net.ipv4.tcp_max_syn_backlog = 65535(半连接队列),必须 ≥somaxconn -
net.core.netdev_max_backlog = 30000(网卡软中断队列),低于 1000 时 Worker 一延迟就丢包
调完执行 sudo sysctl -p,再用 sysctl net.core.somaxconn 验证。否则即使开了 32 个 worker,内核也在 SYN 阶段就把连接静默丢弃了。
最后提醒一句:压测前一定要清缓存,sudo sh -c "echo 3 > /proc/sys/vm/drop_caches",不然第二次跑的数据全是内存命中结果,完全失真。TIME_WAIT 回收不及时、连接池绕过、event 扩展加载失败——这三个点,漏掉任何一个,万级 TPS 都只是纸上谈兵。


















