# WebSocket 功能文档 ## 概述 本项目基于 Laravel-S 和 Swoole 实现了完整的 WebSocket 功能,支持实时通信、消息推送、广播等功能。 ## 功能特性 - ✅ 实时双向通信 - ✅ 用户连接管理 - ✅ 点对点消息发送 - ✅ 群发消息/广播 - ✅ 频道订阅/取消订阅 - ✅ 心跳机制 - ✅ 自动重连 - ✅ 在线状态管理 - ✅ 系统通知推送 - ✅ 数据更新推送 ## 架构设计 ### 后端组件 #### 1. WebSocketHandler (`app/Services/WebSocket/WebSocketHandler.php`) WebSocket 处理器,实现了 Swoole 的 `WebSocketHandlerInterface` 接口。 **主要方法:** - `onOpen()`: 处理连接建立事件 - `onMessage()`: 处理消息接收事件 - `onClose()`: 处理连接关闭事件 **支持的消息类型:** - `ping/pong`: 心跳检测 - `heartbeat`: 心跳确认 - `chat`: 私聊消息 - `broadcast`: 广播消息 - `subscribe/unsubscribe`: 频道订阅/取消订阅 #### 2. WebSocketService (`app/Services/WebSocket/WebSocketService.php`) WebSocket 服务类,提供便捷的 WebSocket 操作方法。 **主要方法:** - `sendToUser($userId, $data)`: 发送消息给指定用户 - `sendToUsers($userIds, $data)`: 发送消息给多个用户 - `broadcast($data, $excludeUserId)`: 广播消息给所有用户 - `sendToChannel($channel, $data)`: 发送消息给指定频道 - `getOnlineUserCount()`: 获取在线用户数 - `isUserOnline($userId)`: 检查用户是否在线 - `sendSystemNotification()`: 发送系统通知 - `pushDataUpdate()`: 推送数据更新 #### 3. WebSocketController (`app/Http/Controllers/System/WebSocket.php`) WebSocket API 控制器,提供 HTTP 接口用于管理 WebSocket 连接。 ### 前端组件 #### WebSocketClient (`resources/admin/src/utils/websocket.js`) WebSocket 客户端封装类。 **功能:** - 自动连接和重连 - 心跳机制 - 消息类型路由 - 事件监听 - 连接状态管理 ## 配置说明 ### Laravel-S 配置 (`config/laravels.php`) ```php 'websocket' => [ 'enable' => env('LARAVELS_WEBSOCKET', true), 'handler' => \App\Services\WebSocket\WebSocketHandler::class, ], 'swoole_tables' => [ 'wsTable' => [ 'size' => 102400, 'column' => [ ['name' => 'value', 'type' => \Swoole\Table::TYPE_STRING, 'size' => 1024], ['name' => 'expiry', 'type' => \Swoole\Table::TYPE_INT, 'size' => 4], ], ], ], ``` ### 环境变量 在 `.env` 文件中添加: ```env LARAVELS_WEBSOCKET=true ``` ## API 接口 ### 1. 获取在线用户数 ``` GET /admin/websocket/online-count ``` **响应:** ```json { "code": 200, "message": "success", "data": { "online_count": 10 } } ``` ### 2. 获取在线用户列表 ``` GET /admin/websocket/online-users ``` **响应:** ```json { "code": 200, "message": "success", "data": { "user_ids": [1, 2, 3, 4, 5], "count": 5 } } ``` ### 3. 检查用户在线状态 ``` POST /admin/websocket/check-online ``` **请求参数:** ```json { "user_id": 1 } ``` **响应:** ```json { "code": 200, "message": "success", "data": { "user_id": 1, "is_online": true } } ``` ### 4. 发送消息给指定用户 ``` POST /admin/websocket/send-to-user ``` **请求参数:** ```json { "user_id": 1, "type": "notification", "data": { "title": "新消息", "message": "您有一条新消息" } } ``` ### 5. 发送消息给多个用户 ``` POST /admin/websocket/send-to-users ``` **请求参数:** ```json { "user_ids": [1, 2, 3], "type": "notification", "data": { "title": "系统通知", "message": "系统将在今晚进行维护" } } ``` ### 6. 广播消息 ``` POST /admin/websocket/broadcast ``` **请求参数:** ```json { "type": "notification", "data": { "title": "公告", "message": "欢迎使用新版本" }, "exclude_user_id": 1 // 可选:排除某个用户 } ``` ### 7. 发送消息到频道 ``` POST /admin/websocket/send-to-channel ``` **请求参数:** ```json { "channel": "orders", "type": "data_update", "data": { "order_id": 123, "status": "paid" } } ``` ### 8. 发送系统通知 ``` POST /admin/websocket/send-notification ``` **请求参数:** ```json { "title": "系统维护", "message": "系统将于今晚 23:00-24:00 进行维护", "type": "warning", "extra_data": { "start_time": "23:00", "end_time": "24:00" } } ``` ### 9. 发送通知给指定用户 ``` POST /admin/websocket/send-notification-to-users ``` **请求参数:** ```json { "user_ids": [1, 2, 3], "title": "订单更新", "message": "您的订单已发货", "type": "success" } ``` ### 10. 推送数据更新 ``` POST /admin/websocket/push-data-update ``` **请求参数:** ```json { "user_ids": [1, 2, 3], "resource_type": "order", "action": "update", "data": { "id": 123, "status": "shipped" } } ``` ### 11. 推送数据更新到频道 ``` POST /admin/websocket/push-data-update-channel ``` **请求参数:** ```json { "channel": "orders", "resource_type": "order", "action": "create", "data": { "id": 124, "customer": "张三", "amount": 100.00 } } ``` ### 12. 断开用户连接 ``` POST /admin/websocket/disconnect-user ``` **请求参数:** ```json { "user_id": 1 } ``` ## 前端使用示例 ### 1. 基本连接 ```javascript import { getWebSocket, closeWebSocket } from '@/utils/websocket' import { useUserStore } from '@/stores/modules/user' const userStore = useUserStore() // 连接 WebSocket const ws = getWebSocket(userStore.userInfo.id, userStore.token, { onOpen: (event) => { console.log('WebSocket 已连接') }, onMessage: (message) => { console.log('收到消息:', message) }, onError: (error) => { console.error('WebSocket 错误:', error) }, onClose: (event) => { console.log('WebSocket 已关闭') } }) // 连接 ws.connect() ``` ### 2. 监听特定消息类型 ```javascript // 监听通知消息 ws.on('notification', (data) => { message.success(data.title, data.message) }) // 监听数据更新 ws.on('data_update', (data) => { console.log('数据更新:', data.resource_type, data.action) // 刷新数据 loadData() }) ``` ### 3. 发送消息 ```javascript // 发送心跳 ws.send('heartbeat', { timestamp: Date.now() }) // 发送私聊消息 ws.send('chat', { to_user_id: 2, content: '你好,这是一条私聊消息' }) // 订阅频道 ws.send('subscribe', { channel: 'orders' }) // 取消订阅 ws.send('unsubscribe', { channel: 'orders' }) ``` ### 4. 发送广播消息 ```javascript ws.send('broadcast', { message: '这是一条广播消息' }) ``` ### 5. 断开连接 ```javascript // 断开连接 ws.disconnect() // 或使用全局方法 closeWebSocket() ``` ### 6. 在 Vue 组件中使用 ```vue 连接 WebSocket 断开连接 发送消息 连接状态: {{ connectionStatus }} ``` ## 消息格式 ### 服务端发送的消息格式 ```json { "type": "notification", "data": { "title": "标题", "message": "内容", "type": "info", "timestamp": 1641234567 } } ``` ### 客户端发送的消息格式 ```json { "type": "chat", "data": { "to_user_id": 2, "content": "消息内容" } } ``` ## 启动和停止 ### 启动 Laravel-S 服务 ```bash php bin/laravels start ``` ### 停止 Laravel-S 服务 ```bash php bin/laravels stop ``` ### 重启 Laravel-S 服务 ```bash php bin/laravels restart ``` ### 重载 Laravel-S 服务(平滑重启) ```bash php bin/laravels reload ``` ### 查看服务状态 ```bash php bin/laravels status ``` ## WebSocket 连接地址 ### 开发环境 ``` ws://localhost:5200/ws?user_id={user_id}&token={token} ``` ### 生产环境 ``` wss://yourdomain.com/ws?user_id={user_id}&token={token} ``` ## Nginx 配置示例 ```nginx server { listen 80; server_name yourdomain.com; root /path/to/your/project/public; location / { try_files $uri $uri/ /index.php?$query_string; } # WebSocket 代理配置 location /ws { proxy_pass http://127.0.0.1:5200; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_read_timeout 86400; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } ``` ## 使用场景 ### 1. 实时通知 ```php // 发送系统通知 $webSocketService->sendSystemNotification( '系统维护', '系统将于今晚进行维护', 'warning' ); ``` ### 2. 订单状态更新 ```php // 推送订单状态更新给相关人员 $webSocketService->pushDataUpdate( [$order->user_id], 'order', 'update', [ 'id' => $order->id, 'status' => $order->status, 'updated_at' => $order->updated_at ] ); ``` ### 3. 实时聊天 ```javascript // 发送私聊消息 ws.send('chat', { to_user_id: 2, content: '你好' }) ``` ### 4. 数据监控 ```php // 推送系统监控数据到特定频道 $webSocketService->sendToChannel('system_monitor', 'monitor', [ 'cpu_usage' => 75, 'memory_usage' => 80, 'disk_usage' => 60 ]); ``` ## 注意事项 1. **连接认证**: WebSocket 连接时需要提供 `user_id` 和 `token` 参数 2. **心跳机制**: 客户端默认每 30 秒发送一次心跳 3. **自动重连**: 连接断开后会自动尝试重连,最多重试 5 次 4. **并发限制**: Swoole Table 最多支持 102,400 个连接 5. **内存管理**: 注意内存泄漏问题,定期重启服务 6. **安全性**: 生产环境建议使用 WSS (WebSocket Secure) 7. **日志监控**: 查看日志文件 `storage/logs/swoole-YYYY-MM.log` ## 故障排查 ### 1. 无法连接 WebSocket - 检查 Laravel-S 服务是否启动 - 检查端口 5200 是否被占用 - 检查防火墙设置 - 查看日志文件 ### 2. 连接频繁断开 - 检查网络稳定性 - 调整心跳间隔 - 检查服务器资源使用情况 ### 3. 消息发送失败 - 检查用户是否在线 - 检查消息格式是否正确 - 查看错误日志 ## 参考资料 - [Laravel-S 文档](https://github.com/hhxsv5/laravel-s) - [Swoole 文档](https://www.swoole.com/) - [WebSocket API](https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket) ## 更新日志 ### 2024-02-08 - ✅ 初始版本发布 - ✅ 实现基础 WebSocket 功能 - ✅ 实现消息推送功能 - ✅ 实现频道订阅功能 - ✅ 实现前端客户端封装 - ✅ 实现管理 API 接口