php 8.1 + swoole 实现 websocket 高并发的关键在于合理配置 worker_num、max_request 和心跳机制:worker_num 宜设为 cpu 核数的 1.5~2 倍;max_request 推荐 1000~3000 防内存泄漏;ping_interval=25000ms、ping_timeout=60000ms 避免连接假死。

PHP 8.1 + Swoole 实现 WebSocket 高并发,核心不在“能不能”,而在于「进程模型配置是否匹配硬件」和「连接生命周期是否被意外拖垮」。实测中,90% 的性能瓶颈不是代码写错,而是 worker_num、max_request、心跳机制这三项配得不合理。
worker_num 和 cpu 核心数怎么配才不翻车
Swoole 的 worker_num 不是越大越好,也不是简单设成 swoole_cpu_num() 就万事大吉。它本质是 Worker 进程数量,每个进程处理一个连接的业务逻辑(比如消息分发),但底层 Reactor 线程数由内核自动管理。
- 在 4 核 CPU 上,
worker_num = 8(即swoole_cpu_num() * 2)通常是更稳的选择,比设成 4 或 16 更能应对突发消息洪峰 - 如果启用了
task_worker_num(比如做日志落库、敏感词过滤),Worker 进程要留出余量,避免被阻塞任务拖慢响应 —— 此时建议worker_num = swoole_cpu_num() * 1.5 - 切忌在 2 核机器上硬设
worker_num = 32:进程切换开销会吃掉大量 CPU,top里能看到%sy(系统态)飙升,但实际吞吐反而下降
max_request 必须设,否则内存泄漏会悄悄干掉服务
PHP 8.1 虽然 GC 更强,但 Swoole 常驻内存模型下,未释放的闭包、全局静态变量、PDO 连接残留仍会导致内存缓慢增长。不设 max_request,单个 Worker 进程跑几天后可能吃光 2GB 内存,然后被系统 OOM killer 杀掉 —— 表现为连接突然断开、server->push() 失败但无报错。
- 生产环境推荐值:
max_request = 1000 ~ 3000,视单次消息处理复杂度调整 - 如果用到了 ThinkPHP/Laravel 等框架的容器或事件监听器,务必压测验证:先设
max_request = 100,观察 1 小时内存增长曲线,再逐步放宽 - 配合
reload_async = true使用,可实现平滑重启,客户端几乎无感知
心跳超时(ping/pong)配错,连接会批量假死
WebSocket 连接空闲时,NAT 网关、云厂商 SLB、甚至某些手机 WiFi 模块会在 60~300 秒后静默断开 TCP 连接,但 Swoole 并不知情,$server->connections 里还留着这个 fd,导致后续 push() 返回 false 或直接崩溃。
- 必须显式开启并调优:
ping_interval = 25000(25 秒发一次 ping)、ping_timeout = 60000(60 秒没收到 pong 就 close) - 前端 JS 一定要响应
onping事件(或至少监听message类型为 ping 的帧),否则服务端等不到 pong,主动断连 - 别依赖浏览器自动回 pong:Chrome/Firefox 对 WebSocket ping 的响应不一致,Swoole 4.8+ 后已默认不自动回复,必须业务层处理
真正卡住高并发上线的,往往不是协议或语法问题,而是这些看似“配置项”的细节 —— 它们不会报错,只会让服务在 2000 连接时还很稳,到 8000 连接时开始丢消息、延迟跳变、凌晨三点默默挂掉。上线前,用 swoole_server->stats() 看一眼 connection_num 和 tasking_num 的实时变化,比读十遍文档都管用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











