workerman 5.2.3 不内置连接分组管理,但可通过 $connection->id、$worker->connections 及自定义数组/redis 等实现:1. 全局数组维护分组映射;2. 动态绑定 $connection->group 属性;3. splfixedarray 或 redis 做高性能索引;4. 封装 broadcasttogroup 方法按组发消息,注意 onclose 清理与 isconnected 检查。

Workerman 5.2.3 本身不内置“连接分组管理”功能,但可以通过其提供的 $connection->id、$worker->connections 和自定义数组/哈希结构,结合业务逻辑轻松实现连接分组(如房间、用户ID、设备类型等维度)。核心思路是:**在连接建立时分配分组标识,运行时维护分组映射关系,发送消息时按组投递**。
1. 使用全局数组维护分组关系
最常用且轻量的方式是在 Worker 启动时定义一个全局分组容器(如 static $groups = []),在 onConnect 中解析客户端身份并加入对应分组:
- 客户端首次连接时(例如 WebSocket 握手携带 token 或 room_id),在
onMessage或onConnect后立即解析参数 - 将
$connection对象存入对应分组,例如:self::$groups['room_1001'][] = $connection; - 注意:需用
$connection->id做键或确保连接对象可被安全引用;断开时务必从所有分组中移除(在onClose中清理)
2. 利用 Connection 的属性绑定分组信息
Workerman 允许给 $connection 动态添加属性,适合单连接归属唯一分组的场景:
- 在
onMessage中解析出分组名后,直接赋值:$connection->group = 'user_123'; - 广播时遍历
$worker->connections,筛选匹配连接:foreach ($worker->connections as $conn) { if ($conn->group === 'user_123') { $conn->send(...); } } - 优点是无需额外存储结构,缺点是无法快速获取某组全部连接(需全量遍历)
3. 使用 SplFixedArray 或 Redis 做高性能分组索引(进阶)
当连接数大(万级+)或需跨 Worker 进程共享分组时,建议外接索引:
- 本地高性能索引:用
SplFixedArray配合哈希(如 crc32(group_name) % size)减少冲突,比普通数组查找更快 - 分布式场景:用 Redis 的
SET或Hash存储分组成员,例如:redis->sAdd('group:room_2001', $connection->id);配合 Workerman 的异步 Redis 客户端(如workerman/redis)操作 - 注意:Redis 方案需在
onClose中主动删除 ID,避免僵尸连接;建议设置连接超时自动清理(TTL)
4. 发送消息到指定分组的实用写法
无论用哪种存储方式,发消息逻辑应封装复用。示例(基于内存数组):
- 定义方法:
public static function broadcastToGroup($groupName, $data) { foreach (self::$groups[$groupName] ?? [] as $conn) { if ($conn->isConnected()) { $conn->send($data); } } } - 支持 JSON 消息:
$conn->send(json_encode(['type'=>'msg','content'=>$text], JSON_UNESCAPED_UNICODE)); - 避免遍历时连接已关闭:始终检查
$conn->isConnected(),防止 warning
不复杂但容易忽略的是清理时机和并发安全——如果多个 Worker 进程共用同一分组数组,必须改用 Redis;单进程下注意 onClose 里及时 unset,否则内存泄漏。分组本质是业务建模,Workerman 提供的是连接生命周期钩子和底层通信能力,分组逻辑由你定义。











