ThinkPHP 8.0 最稳,think-swoole 已深度集成 WebSocket;5.1 依赖 PHPSocket.IO 配置繁琐,6.0 初期配置项命名混乱;TP 本身不支持 WebSocket,需 Swoole 独立常驻进程,不可在控制器中直接 new。

ThinkPHP 5.1/6.0/8.0 哪个版本真能跑 WebSocket?
TP 本身不带 WebSocket 服务,所有版本都得靠外部扩展——但支持方式和成熟度差异极大。5.1 只能靠 PHPSocket.IO(基于 Workerman),配置繁琐、调试困难;6.0 开始官方推出 think-swoole,但早期版本对 websocket 配置项命名不统一(比如 enabled vs enable),容易配错;8.0 是目前最稳的,think-swoole 已深度集成,websocket.handler、room 内存表等关键能力开箱即用。
为什么不能直接在 TP 控制器里写 new swoole_websocket_server()?
这不是语法错误,而是架构冲突:TP 是请求-响应模型,每次 HTTP 请求结束,PHP 进程就销毁;而 WebSocket 必须长驻内存、持续监听连接。硬塞进控制器会导致服务一响就死,或被 FPM 自动回收。正确做法是让 Swoole 独立启一个常驻进程,TP 只负责业务逻辑(比如用户登录、消息入库),再通过 Redis pub/sub 或 HTTP API 和 WebSocket 进程通信。
swoole_cpu_num() * 2 这个 worker_num 值到底怎么调?
这是最容易拍脑袋填错的配置。设太高会争抢 CPU、触发上下文切换抖动;设太低则并发扛不住,连接排队超时。实际要看真实负载:
– 日活 worker_num => 4 足够
– 实时聊天、设备心跳密集(每 30 秒一次):建议先设 swoole_cpu_num() * 2,再用 ab 或 wrk 压测,观察 top 中 CPU idle 是否长期低于 20%
– 宝塔环境别忘了在「安全组」和「防火墙」里放行 WebSocket 端口(如 9501 或 8080),否则客户端连都连不上,还以为是代码问题
WebSocket 连接成功但收不到消息?先查这三件事
这种问题 80% 出在通信链路断点上,不是 TP 写错了:
– 检查 Redis 是否正常运行,redis-cli ping 返回 PONG 才算通
– 查看 WebSocket 进程日志里有没有 subscribe 成功记录,没订阅就收不到 TP 发来的消息
– 客户端连的是 ws:// 还是 wss://?如果 Nginx 做了反向代理,必须在配置里显式透传 Upgrade 和 Connection 头,漏掉任意一个,握手就会失败,浏览器控制台报 ERR_CONNECTION_REFUSED 或 net::ERR_SSL_PROTOCOL_ERROR
立即学习“PHP免费学习笔记(深入)”;
真正难的从来不是“怎么连上”,而是“怎么让成千上万个连接稳定在线、不丢消息、不串用户”。心跳间隔、离线消息兜底、房间绑定逻辑、FD 与 UID 映射一致性——这些细节不压到线上流量里根本看不出问题。



















