channel组件仅支持单机多进程通信,因其底层基于本机内存和flock文件锁,server绑定127.0.0.1等本地地址,无法跨服务器;跨机需改用redis pub/sub、kafka等方案。

Channel 组件不能实现跨服务器通信,它只支持同一台机器、同一个 Workerman 主进程启动的多个子进程之间广播。跨服务器必须换方案,比如 Redis Pub/Sub 或 Kafka。
为什么 Channel 无法跨服务器?
Channel 的底层是内存 + 文件锁(flock),所有数据存在本机内存里,服务端 Channel\Server 进程也只监听本地地址(如 127.0.0.1:2206)。一旦部署到多台机器,publish() 发出去的消息根本到不了另一台机器上的 Channel\Client。
常见错误现象:
- 本地开发一切正常,一上云服务器或 Docker 就收不到广播
- 两台机器都起了
Channel\Server,但互相完全不感知 -
publish()返回 true,但对端on()回调从不触发——因为根本没连上正确的 Server
Channel 跨进程通信的硬性前提
必须满足以下全部条件,publish/subscribe 才能工作:
- 所有 Worker 进程(包括 Gateway、BusinessWorker 等)由**同一个主进程启动**(即同一条
php start.php start命令) -
Channel\Server必须显式启动,且端口未被占用;不能只new \Workerman\Channel\Client()就完事 - 客户端连接地址必须和 Server 绑定地址严格一致:写
127.0.0.1就不能写localhost,写0.0.0.0就得用127.0.0.1或实际内网 IP 连接 - 每个
Channel\Client实例必须调用connect(),建议加超时判断:if (!$client->connect()) { exit("channel connect failed"); }
替代跨服务器通信的可行方案
如果你真需要跨机器广播或点对点推送,Channel 应该直接放弃,改用这些:
-
Redis的PUB/SUB:延迟低、易部署、支持断线重连;Workerman 官方推荐,GatewayWorker默认就依赖它 -
Redis列表(LPUSH+BRPOP):适合任务分发类场景,比 Pub/Sub 更可靠 -
Kafka或RabbitMQ:适用于高吞吐、需持久化、有 ACK 要求的业务 - 自建 TCP 中央转发服务:用 Workerman 写一个长期运行的
tcp://0.0.0.0:xxxx服务,所有机器上的 Worker 都连它中转消息——但运维成本高,不如直接上 Redis
注意:不要试图用 Channel + 反向代理 / NAT / SSH 隧道“绕过”限制——它不是为网络通信设计的,强行改造只会让连接不稳定、锁失效、内存泄漏。
容易被忽略的关键细节
很多人卡在看似“通了”,实则无效的环节:
-
Channel\Client::on()是注册回调,不是一次性接收;如果进程重启,必须重新connect()和on(),否则后续消息全丢 -
publish($channel_name, $data)会自动json_encode(),所以别传resource、Closure或含循环引用的数组,否则静默失败 - 一个 Client 实例对同一频道重复调用
on(),会覆盖前一个回调——不是叠加,这点和 EventEmitter 不同 - Docker 容器里跑
Channel\Server时,记得用host.docker.internal或宿主机 IP 连接,别用127.0.0.1(容器内指向自己)











