Workerman不内置红点逻辑,仅提供长连接通道;红点由前端根据服务端推送的轻量通知(如{type:"like",count:1})自主控制显示与累加,需用Redis存储user_id→connection_id映射实现跨进程精准推送,离线消息写入Redis List兜底。

Workerman 本身不内置“红点通知”逻辑,它只负责长连接通信;红点本质是客户端状态标记,服务端只需在有新互动时,向目标用户推送一条轻量消息(比如 {type: "like", count: 1}),由前端决定是否亮红点、怎么累加、是否去重。
用 Worker 启动 WebSocket 服务,别碰 GatewayWorker 的默认路由
小红书类场景对实时性要求高、但消息结构简单,直接用 WebServer + WebSocketConnection 更可控。很多人一上来就套 GatewayWorker,结果被 register/gateway 双进程模型绕晕,连谁该发消息给谁都没理清。
-
GatewayWorker适合需要广播、跨 Gateway 路由的中大型系统,点赞/评论这种点对点或单房间通知,纯Worker足够且调试更直观 - 不要在
onMessage里直接调$connection->send()给自己——那是回显,不是通知;红点要推给「被点赞的人」,得先查出对方的$connection实例 - 用
$_SESSION或 Redis 存user_id → connection_id映射,别依赖 Workerman 自带的Context,它不跨进程持久
点赞后怎么精准推给被点赞者?用 Redis 做在线状态+连接寻址
Workerman 进程间不共享内存,$connections 是单进程私有变量。你在一个 Worker 进程里收到点赞请求,但被点赞者的连接可能在另一个进程上——必须靠外部存储做路由。
在 Linux 上通过 Chrome 挂载/VNC 自动发布小红书长笔记。Agent 撰写标题和正文后执行 xhs_publish.sh --publish --submit,触发小红书发布。
- 用户登录成功后,存一条 Redis Hash:
HSET user_conn_map {user_id} {connection_id},过期时间设为 5 分钟(配合心跳续期) - 收到点赞请求(比如
{"action":"like","target_user_id":123}),先HGET user_conn_map 123拿到连接 ID,再通过Worker::getConnectionByUid()(需提前在onConnect里调$connection->uid = $user_id)获取连接对象 - 如果
HGET返回空,说明对方不在线,此时可写入离线队列(如 Redis List),上线后拉取——红点数不能丢,但也不必强一致
onMessage 里别直接拼 JSON,用 json_encode($data, JSON_UNESCAPED_UNICODE)
中文字段(比如 "msg": "赞了你的笔记")若不加 JSON_UNESCAPED_UNICODE,前端收到的是 Unicode 转义串 "\u8d5e\u4e86\u4f60\u7684\u7b14\u8bb0",JS JSON.parse() 虽能解,但调试时眼花,日志也难读。
- 所有推送消息统一结构,例如:
{"event":"notification","type":"like","from_user_id":456,"timestamp":1717023456},前端靠type判断是否触发红点 - 避免在
onMessage中做耗时操作:查库、调第三方 API、生成缩略图……这些必须扔进异步任务(如AMQP或Redis BLPOP队列),否则会阻塞整个 Worker 进程 - 测试时用
telnet或wscat直连 WebSocket 端口,比反复刷网页快得多:wscat -c ws://127.0.0.1:2346 --no-check
真正麻烦的从来不是推送那行 $connection->send(),而是「谁在线」「谁该收」「收了怎么合并去重」「离线期间的消息怎么兜底」——这些状态管理逻辑全得自己补,Workerman 只提供连接管道。红点数字一旦开始跨设备同步(比如手机 App 和网页同时在线),就得引入版本号或时间戳做冲突判断,这时候光靠 Redis Hash 就不够了。


















