Webman本身不提供开箱即用的匿名社交能力,需自行设计临时身份、无状态消息路由及Redis映射机制,避免依赖PHP session,确保全程基于客户端token和WebSocket上下文实现隔离与可扩展性。

Webman 本身不是通用框架,它不直接提供“匿名社交”开箱即用的能力——你得自己控制用户标识、会话生命周期和消息路由逻辑。它的高性能来自底层 Workerman 的异步非阻塞模型,但匿名性必须由你设计实现。
为什么 app\controller\UserController 不该存用户登录态
匿名社交的核心是「无账号体系」或「临时身份」。一旦你在 UserController::index() 里调用 $request->session()->set('user_id', $id),就等于把匿名用户拖进了传统会话陷阱。
常见错误现象:
- 用户刷新页面后身份丢失(session cookie 过期或未持久化)
- 多个标签页产生冲突 session ID,导致消息错发
- Redis session 存储引入不必要的序列化开销,抵消 Webman 的内存优势
正确做法是:用客户端生成的随机 token(如 UUID v4)作为临时用户 ID,全程通过 WebSocket 连接上下文或 HTTP Header 透传,不依赖 PHP session。
示例:
$temp_id = bin2hex(random_bytes(16)); // 服务端生成,返回给前端存储于 localStorage
onMessage 中如何隔离匿名用户消息流
Workerman 的 onMessage 回调里,$connection 对象自带唯一 $connection->id,但它只在单进程内有效;跨 Worker 进程时无法全局识别同一匿名用户。
所以不能只靠 $connection->id 做路由。你需要一个轻量级的全局映射:
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 用 Redis 的
HSET anonymous_users绑定临时 ID 到当前连接 - 设置 TTL(比如 30 分钟),避免僵尸连接堆积
- 在
onClose里主动HDEL anonymous_users
这样私聊或房间广播时,就能用 temp_id 查出目标连接,而不是盲目遍历 $connection->worker->connections。
WebSocket 消息体结构必须带 from 和 to 字段
匿名场景下,前端发来的每条消息都应显式声明来源与目标,后端不做隐式推断。否则容易出现「A 发的消息被 B 收到却显示来自 C」这类错乱。
推荐消息格式(JSON):
{"type":"chat","from":"a1b2c3d4","to":"room:general","content":"hello"}
关键点:
-
from必须是前端传入的temp_id,服务端只校验其存在性,不生成或覆盖 -
to支持两种值:room:xxx(广播)、user:xxx(单聊),便于后续扩展 - 不要在服务端自动补全字段——匿名系统里,任何“智能默认”都是信任漏洞
别忽略 start.php start -d 启动后的连接复用问题
Webman 默认使用守护进程模式(-d),Worker 进程长期存活。如果匿名用户频繁断连重连,而你没在 onClose 清理 Redis 映射或连接缓存,会导致:
- 内存泄漏:每个新连接都新建对象,旧连接残留引用不释放
- 消息积压:已断开的
connection仍留在 Worker 的 connections 数组中,广播时触发 send 失败警告 - Redis 键爆炸:大量过期但未清理的
temp_id占满 key 空间
务必在 onClose 回调中做三件事:
- 从 Redis 删除该 temp_id 映射
- 调用 unset($connection->worker->connections[$connection->id])(虽 Workerman 内部会清,但显式操作更可控)
- 记录日志(如 error_log("Closed: {$temp_id}")),方便排查连接异常
匿名不是功能开关,而是整个数据流的设计约束。Webman 的快,只在你让每条请求都保持无状态、无依赖、无隐式上下文时才真正兑现。










