Workerman 5.2.3 消息广播需手动遍历 $worker->connections 并调用 send(),支持基础单进程广播、Redis/GatewayWorker 跨进程广播及按 uid/群组定向广播,须校验连接有效性并注意 JSON 编码、限流与心跳清理。

Workerman 5.2.3 实现消息广播推送,核心在于“遍历当前所有活跃连接并调用 send()”。它本身不提供 broadcast() 这样的封装方法,但机制清晰、控制自由——你决定推给谁、什么时候推、内容怎么组织。
基础广播:遍历 connections 发送
这是最直接的方式,适用于单进程、轻量级场景。服务端启动后,所有 WebSocket 或 TCP 连接都保存在 $worker->connections 中,每个元素都是一个可写的连接对象。
- 确保连接对象有效:检查
$connection->isConnected()(Workerman 5.x 推荐用法),避免向已断开的连接写入导致警告 - 发送前可做简单过滤:比如跳过某些状态异常的连接,或只推给特定协议类型(如仅 WebSocket)
- 示例代码片段:
use Workerman\Worker;
require_once __DIR__.'/vendor/autoload.php';
$ws = new Worker('websocket://0.0.0.0:2000');
$ws->count = 1;
$ws->onWorkerStart = function ($ws) {
echo "Server started\n";
// 每 5 秒向所有在线客户端广播一次
Timer::add(5, function () use ($ws) {
foreach ($ws->connections as $connection) {
if ($connection->isConnected()) {
$connection->send(json_encode(['type' => 'notice', 'msg' => '服务器心跳广播']));
}
}
});
};
Worker::runAll();
跨进程广播:必须借助外部通信机制
Workerman 默认多进程时,各 worker 进程内存隔离,$worker->connections 仅包含本进程内的连接。若启动了 4 个进程,想让一条消息触达全部客户端,需引入进程间协调手段:
- Redis Pub/Sub:最常用。一个进程发布消息到频道,其余所有进程订阅该频道并各自向本进程连接广播
- GatewayWorker:官方推荐方案。分离 gateway(负责连接管理与协议解析)和 businessWorker(负责业务逻辑),通过 GatewayClient 向指定 uid/group 广播,天然支持跨进程
- 文件/数据库轮询(不推荐):延迟高、性能差,仅用于极低频调试场景
按用户或群组定向广播
真实业务中极少全量广播,更多是“推给某用户所有设备”或“推给某个聊天室成员”。关键在于建立映射关系:
- 连接时绑定 uid:客户端首次发包带上用户标识(如
{"type":"login","uid":123}),服务端存入$connection->uid = 123 - 维护全局映射表:可用静态数组、Swoole\Table(若混用)、或 Redis Hash 存储
uid → [conn_id1, conn_id2] - 广播时查表+遍历:取出目标 uid 对应的所有连接,逐个
send();注意连接有效性校验
注意事项与避坑点
广播看似简单,实际运行中容易出问题:
- JSON 编码失败会导致整个 send 失败,建议用
json_encode($data, JSON_UNESCAPED_UNICODE)并判断返回值 - 高频广播(如每秒多次)可能压垮客户端,建议加限流或合并消息
- 大消息体(>1MB)易触发 WebSocket 分片或内存溢出,需分块或压缩
- 务必设置心跳与超时清理:否则
connections会累积大量僵尸连接,广播变慢甚至卡死

















