
WebSocket 在 Yii2 里不能直接用 yii\web\Socket
Yii2 官方不提供 WebSocket 支持,yii\web\Socket 根本不存在——这是常见误解的源头。你搜到的“Yii2 内置 WebSocket”基本是混淆了扩展名或误读文档。真要跑 WebSocket,得靠外部服务进程,Yii2 只负责配合握手、推送、状态管理。
workerman/yii2-workerman 扩展只是胶水,不是替代方案
这个扩展本质是把 Workerman 的事件循环和 Yii2 的生命周期做轻量桥接,它不接管 HTTP 请求,也不替换 Web 服务器。真正干活的是 Workerman\Worker 实例,Yii2 只用来加载配置、调用模型、查数据库。
yii2-workerman 不处理 WebSocket 协议细节,比如帧解析、ping/pong、连接升级响应——全由 Workerman 底层完成它默认只注册一个 onMessage 回调,但你要做用户认证、房间管理、心跳续连,都得自己写逻辑,不能依赖 Yii2 的中间件或行为启动命令是 php yii websocket/start,但实际执行的是 Workerman\Worker::runAll(),和 yii serve 完全无关,别指望它能热重载控制器
连接鉴权必须在 onConnect 里手动做,且不能用 Yii2 Session
WebSocket 握手是独立于 HTTP 的 TCP 连接,$_SESSION 和 Cookie 在 onConnect 阶段不可用。常见错误是试图在回调里调 Yii::$app->user->isGuest,结果永远是 true。
正确做法:客户端在首次 send() 时带上 token 或 user_id,服务端在 onMessage 中解析并验证,再绑定到连接实例(例如 $connection->user_id = $uid)Token 验证建议走 Yii::$app->getSecurity()->validatePassword() 或 JWT 解析,别硬编码密钥Workerman 的 $connection 对象不持久化,断线后所有属性丢失,别存大对象或 DB 连接
广播性能瓶颈不在 Yii2,而在 Workerman 的连接遍历方式
用 foreach ($worker->connections as $conn) 推送消息看着简单,但连接数过千时延迟明显。这不是 Yii2 慢,是 PHP 单进程遍历开销本身高。
避免在广播前查数据库——比如“查出所有在线管理员再推”,应提前维护内存映射(如 Worker::$adminConnections = [])不要在 onMessage 里直接 sleep() 或调用阻塞 IO,Workerman 是异步单线程,一卡全卡生产环境务必关掉 debug 模式,Workerman 的 Worker::$daemonize = true 和 Worker::$logFile 要显式配置,否则日志刷爆磁盘
最易被忽略的一点:Workerman 进程不共享内存,Yii::$app 实例在每个 Worker 子进程中都是全新创建的,所以 Yii::$app->db 连接不会复用,也别想用 static 变量跨进程存状态。

评论(0)