Webman禁用server->push()群发,须改用读扩散+消息中心架构:消息只写一次至Redis Streams/Kafka,客户端按游标拉取;实时推送则由Webman推给在线状态服务异步下发。

Webman 不是「开箱即用」的推送框架,直接调用 $session->send() 或 server->push() 做群发,在千人以上规模就会暴露内存暴涨、worker 卡死、消息积压等硬伤——这不是配置问题,是架构层面的误用。
别用 server->push() 广播群消息
Webman 的 server->push() 是同步遍历所有 session 并逐个 write,单条消息触发百万次序列化+网络写入,CPU 和内存瞬间拉满。实际压测中,5 万在线用户发一条群消息,worker 进程会卡住 3 秒以上,期间新连接被拒绝、心跳超时、onClose 堆积。
- 必须禁用全局广播逻辑,哪怕只在开发环境试过一次也不行
- 改用「读扩散」:消息只写一次到
Redis Streams或Kafka,客户端按游标拉取 - 若需实时触达,Webman 只推给轻量级「在线状态服务」(如 Go 写的网关协调器),由它查分片路由表、异步下发
- 临时应急可用
server->getClientInfo()+ 分片循环,但单次最多触达10000个 session,且要加usleep(1000)防抖
webman/push 插件适合中小场景,但别当「万能胶」
webman/push 封装了 Pusher 协议兼容层,对私有频道鉴权、事件订阅、自动重连都做了封装,trigger('user-1', 'message', [...]) 看似简单,但背后依赖的是独立的推送服务进程(默认监听 :3232)。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 它不共享 Webman 的 session 状态,用户在线与否靠客户端心跳维持,服务端无感知
- 群消息仍走广播模式,
trigger('group-123', ...)本质仍是遍历所有订阅该 channel 的连接,上限约 2 万并发连接就吃紧 - 私有频道鉴权接口
/plugin/webman/push/auth必须返回200+ JSON,否则前端subscribe()会静默失败 - 上线前务必用
ab -n 10000 -c 500 http://x.x.x.x/plugin/webman/push/auth测压,避免鉴权成为瓶颈
未读数和在线状态不能塞进 Webman 主循环
Webman 的事件循环不是为高频小包设计的。onMessage 里做 Redis::hIncrBy('online:shard_001', $uid, 1),或在 onClose 里删 Hash 字段,会导致连接关闭延迟、心跳响应超时、消息堆积。
- 在线状态必须用 Redis Hash 分片存储,key 形如
online:shard_001,用HSET/HDEL原子操作,严禁加锁 - 未读数改用
zset:key 为unread:{group_id}:{user_id},score 存最后已读msg_id,新消息来时用ZCOUNT算差值 - 心跳检测必须剥离为独立协程,比如每 30 秒启动一个
tick定时器扫online:*,发现超时连接再通知 Webman 主进程踢人 - 所有 Redis 操作必须用连接池(如
webman/redis),禁用直连,否则phpredis阻塞会拖垮整个 worker
消息可靠性不能依赖内存队列
Webman 没有内置消息持久化机制。onMessage 回调里处理失败、worker 异常退出、服务器重启——这些都会导致消息丢失。尤其在金融类通知、订单状态变更等强一致性场景下,裸用 Webman 的 WebSocket handler 是危险的。
- 关键消息必须先落库(MySQL 或 TiDB),再发到消息中间件(Kafka / Pulsar),WebSocket 层只做「投递确认」
- 客户端需实现「消息去重 ID」+ 服务端
Redis SETNX msg_id:xxx 3600,防重复消费 - 离线消息兜底不能靠 Webman 缓存,得用独立服务轮询未读表,定时推送到
user-{uid}channel - 上线前跑一次「kill -9 所有 worker 进程」测试,验证消息是否真能从 DB/Kafka 恢复,而不是凭感觉认为“应该没问题”
真正难的不是写通 WebSocket 连接,而是把「状态同步」「消息分发」「故障恢复」这三件事从 Webman 的主事件循环里彻底剥离开——它们各自有节奏、有延迟容忍度、有失败重试策略,混在一起只会让系统越来越不可控。

















