workerman tcp多客户端连接管理本质是每个连接绑定唯一$connection对象并由事件回调驱动;onconnect提供该实例,支持挂载业务标识、遍历worker::$connections广播,onclose必须清理资源防泄漏,onmessage须避免阻塞操作,onerror需主动close防假连接。

Workerman TCP 多客户端连接管理,本质是靠每个连接绑定一个独立的 $connection 对象,并通过事件回调驱动状态流转——不是靠你“轮询”或“查表”,而是靠框架在事件触发时把当前连接对象直接塞给你。
onConnect 回调里拿到的 $connection 就是唯一身份凭证
每次有新 TCP 客户端连上来,onConnect 就会被调用一次,参数 $connection 是该客户端专属的连接实例。它自带生命周期、缓冲区、自定义属性支持,且在整个连接存续期间保持唯一和稳定。
- 不要试图用 IP+端口拼字符串做 key 去自己维护连接池,
$connection本身就可以当数组键(PHP 支持对象作 array key) - 可以在
$connection->uid = 'user_123'这样挂业务标识,后续所有事件(onMessage、onClose)里都能取到 - 若需广播给所有在线连接,直接遍历
Worker::$connections数组即可,里面全是活跃的$connection实例
onClose 中必须清理关联资源,否则内存泄漏不可避免
onClose 是连接断开的最终出口,但很多人只写日志,忘了清理。只要你在 $connection 上挂了任何引用(比如闭包、PDO、Redis 实例、定时器),不手动解除,这个连接对象就无法被 GC 回收。
- 务必检查是否设置了
$connection->timer_id,用Timer::del($connection->timer_id)清掉 - 如果绑定了数据库连接(如
$connection->db),应显式调用$connection->db = null - 若用了
Connection::$connections全局数组做索引,记得 unset 对应项,避免“幽灵连接”残留
大量连接下,别在 onMessage 里做同步阻塞操作
Workerman 的高并发依赖单进程内事件循环轮转,一旦某个 onMessage 里执行了 sleep()、file_get_contents() 或未加超时的 curl_exec(),整个 Worker 进程就会卡住,所有其他连接的读写都会延迟。
- 数据库查询必须用异步驱动(如
workerman/mysql),不能用 PDO 或 MySQLi 同步扩展 - HTTP 请求优先用
GuzzleHttp\Handler\CurlMultiHandler或Workerman\Http\Client,确保非阻塞 - 复杂计算或文件处理建议推到
amqp/redis queue异步执行,再通过$connection->send()回传结果
连接异常中断时,onError 不会自动触发 onClose,得自己补逻辑
onError 和 onClose 是两个独立事件。onError 表示底层 socket 出错(如网络闪断、对端 RST),但此时连接对象可能还“活着”,Worker::$connections 里仍存在,onClose 却不会自动来。
- 在
onError回调里,要主动调用$connection->close(),强制走一遍关闭流程 - 否则该
$connection会一直留在内存里,且无法再 send,形成“假连接” - 配合心跳(
ping/pong)可提前发现这类异常,比等onError更可靠
真正难的不是怎么存连接,而是怎么让每个连接在生命周期内不拖垮整个 Worker——关键点永远落在「事件回调是否轻量」「资源是否及时释放」「异常路径是否全覆盖」这三件事上。











