初始化
This commit is contained in:
53
.cursor/skills/websocket-service/SKILL.md
Normal file
53
.cursor/skills/websocket-service/SKILL.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
name: websocket-service
|
||||
version: 1.0.0
|
||||
description: "在 Hyperf 中搭建 Swoole WebSocket 服务器。当需要实时通信、消息推送或通知功能时使用。含心跳检测和前端集成。"
|
||||
---
|
||||
|
||||
# Swoole WebSocket Service
|
||||
|
||||
## 触发条件
|
||||
|
||||
用户需要实时通信功能:通知推送、在线状态、实时数据更新、聊天功能。
|
||||
|
||||
## 执行流程
|
||||
|
||||
### Phase 0: 加载规范
|
||||
|
||||
读取 `.cursor/rules/016-swoole.mdc`、`013-backend.mdc`,提取 WebSocket 配置、协程安全、fd 存储、心跳、认证鉴权。
|
||||
|
||||
### Phase 1: 服务端配置
|
||||
|
||||
`config/autoload/server.php` 添加 ws 服务,type SERVER_WEBSOCKET,port 环境变量,callbacks ON_HAND_SHAKE/ON_MESSAGE/ON_CLOSE。
|
||||
|
||||
### Phase 2: 连接管理器
|
||||
|
||||
WebSocketConnectionManager:Redis 存储 fd→userId/serverId,userId→{serverId:fd} 集合。addConnection、removeConnection、getUserConnections、getUserIdByFd、isOnline。支持多服务器。
|
||||
|
||||
### Phase 3: WebSocket Controller
|
||||
|
||||
OnOpen:query token 验证 JWT,无效 close,addConnection,push connected。OnMessage:ping→pong。OnClose:removeConnection。
|
||||
|
||||
### Phase 4: 消息推送服务
|
||||
|
||||
WebSocketPushService:pushToUser、pushToUsers、broadcast(Redis publish 跨服)。Inject Sender、ConnectionManager。
|
||||
|
||||
### Phase 5: 前端客户端
|
||||
|
||||
WebSocketClient:connect(url?token=)、on(type, callback)、心跳 30s、断线指数退避重连。完整实现见 **Tier 3**。
|
||||
|
||||
## 验证
|
||||
|
||||
1. [ ] WebSocket 在配置端口启动
|
||||
2. [ ] Token 认证成功才连接
|
||||
3. [ ] 无效 Token 立即断开
|
||||
4. [ ] 心跳 30s 正常
|
||||
5. [ ] 断线自动重连
|
||||
6. [ ] 连接信息存 Redis
|
||||
7. [ ] 推送正确到达目标用户
|
||||
|
||||
## Tier 3 深度参考
|
||||
|
||||
| 文件 | 内容 |
|
||||
|------|------|
|
||||
| `references/ws-implementation.md` | 配置、ConnectionManager、Controller、PushService、前端 Client 完整代码 |
|
||||
@@ -0,0 +1,45 @@
|
||||
# WebSocket Service — 实现细节
|
||||
|
||||
> 主流程见 SKILL.md,本文档为服务端配置、连接管理器、Controller、推送服务、前端客户端的完整代码。
|
||||
|
||||
## 服务端配置
|
||||
|
||||
```php
|
||||
// config/autoload/server.php
|
||||
[
|
||||
'name' => 'ws',
|
||||
'type' => Server::SERVER_WEBSOCKET,
|
||||
'host' => '0.0.0.0',
|
||||
'port' => (int) env('WEBSOCKET_PORT', 9502),
|
||||
'callbacks' => [
|
||||
Event::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],
|
||||
Event::ON_MESSAGE => [...],
|
||||
Event::ON_CLOSE => [...],
|
||||
],
|
||||
]
|
||||
```
|
||||
|
||||
## 连接管理器
|
||||
|
||||
WebSocketConnectionManager:Redis HASH `ws:conn:{fd}` 存 user_id/server_id/connected_at。Redis SET `ws:user:{userId}` 存 `{serverId}:{fd}`(支持多连接)。addConnection、removeConnection、getUserConnections、getUserIdByFd、isOnline。
|
||||
|
||||
## WebSocket Controller
|
||||
|
||||
OnOpenInterface:从 query token 验证 JWT,无效则 close。addConnection。push connected 消息。OnMessageInterface:解析 type,ping→pong。OnCloseInterface:removeConnection。validateToken 返回 userId。
|
||||
|
||||
## 消息推送服务
|
||||
|
||||
WebSocketPushService:pushToUser(userId, type, data) 遍历 getUserConnections,Sender->push。pushToUsers 循环 pushToUser。broadcast 用 Redis publish 跨服务器。
|
||||
|
||||
## 前端 WebSocketClient
|
||||
|
||||
```typescript
|
||||
class WebSocketClient {
|
||||
constructor(url, token) {}
|
||||
connect() { this.ws = new WebSocket(`${url}?token=${token}`) }
|
||||
onmessage → emit(type, data)
|
||||
on(type, callback) → 返回 unsubscribe
|
||||
startHeartbeat() 30s ping
|
||||
onclose → scheduleReconnect 指数退避
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user