webman 是 php 高性能常驻进程框架,websocket 支持基于 workerman/workerman(≥4.1.0),需确认版本匹配、正确启用配置、处理混合消息类型、避免阻塞操作、安全广播、显式心跳保活及 onclose 内存清理。

Webman 是 PHP 生态中一个高性能、事件驱动的常驻进程框架(注意:不是 Java/C 框架,知识库中多处混淆为 Java/C 属误),其 WebSocket 支持基于 workerman/workerman 底层,开箱即用。要实现稳定可用的即时通讯功能,关键不在“能不能连上”,而在于连接管理、消息路由、状态同步和错误兜底——这些才是线上踩坑最多的地方。
确认 Webman 版本与依赖是否匹配
Webman 从 v1.4 起内置 WebSocket 支持,但前提是已正确安装 workerman/workerman(≥4.1.0)。常见错误是手动引入旧版 Workerman 或混用 Composer 自动加载冲突:
-
composer require workerman/workerman必须执行,且不能降级到 3.x - 检查
vendor/workerman/workerman/Worker.php中是否存在onWebSocketConnect方法(v4.1+ 才有) - 若使用 Webman v2.x,需确认
config/plugin/webman/websocket/app.php已启用(默认开启) - 运行
php start.php status时应看到websocket进程在监听,而非仅http
定义 onMessage 时必须处理二进制与文本混合输入
onMessage 回调接收的 $data 可能是 string(UTF-8 文本)或 binary(如图片 base64、protobuf payload),不加判断直接 json_decode($data) 会静默失败或触发 warning。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 先用
is_string($data) && mb_detect_encoding($data, ['UTF-8'], true)初步验证文本性 - 更稳妥的做法是约定协议头,例如前 2 字节为
\x00\x01表示 JSON 文本,\x00\x02表示二进制包 - 避免在
onMessage中做耗时操作(如 DB 查询、HTTP 调用),应投递到Timer::add()或独立 Worker 处理 - 未 catch 的异常会导致当前连接被 Workerman 强制关闭,且无日志 —— 务必包一层
try/catch
广播消息前必须过滤掉 sender 连接(除非是回显)
Webman 默认不提供全局连接池,$connection->send() 只发给单个连接;广播需手动遍历 Worker::$connections。但这里有两个易错点:
-
Worker::$connections是静态属性,包含所有类型连接(HTTP/WS/TCP),必须用$conn instanceof \Workerman\Connection\WebSocketConnection过滤 - 遍历时若某连接已断开(如客户端关页),
$conn->send()会抛出Connection reset by peer异常,必须捕获并 unset - 不要在循环内调用
unset(Worker::$connections[$id]),应先收集待删 ID,再统一清理,否则可能跳过后续连接 - 高并发下直接遍历全部连接性能差,建议按房间 ID 维护独立连接数组(如
$rooms['room_123'][] = $connection)
心跳检测与连接超时必须显式配置
浏览器 WebSocket 默认无心跳,NAT 网关或代理(如 Nginx)通常 60 秒断连。Webman 不自动发送 ping/pong,靠客户端保活极易失联。
- 在
onConnect中启动定时器:Timer::add(25, function() use ($connection) { $connection->send(''); });(空字符串触发 pong) - 设置
$connection->pingNotResponseLimit = 2,连续 2 次 pong 未响应则主动 close - Nginx 反向代理需加配置:
proxy_read_timeout 75;、proxy_set_header Upgrade $http_upgrade;、proxy_set_header Connection "upgrade"; - 客户端 JS 侧也应实现重连逻辑,且首次重连延迟不应为 0(避免雪崩),推荐指数退避:1s → 2s → 4s → 8s
WebSocketConnection 对象会持有闭包、上下文和未释放的资源引用。一旦忘记在 onClose 中清理自定义属性(如 $connection->room_id、$connection->user_id),长连接越多,内存增长越快——这不是配置问题,是代码里没写 unset($connection->user_id)。










