- 新增反向WebSocket管理器模块,支持多客户端连接 - 实现负载均衡机制,自动选择健康且负载最低的客户端 - 添加防重复事件处理机制,防止消息重复处理 - 更新配置模型和加载器以支持反向WebSocket配置 - 添加示例文件和文档说明使用方法 - 修改主程序启动逻辑以支持反向WebSocket服务
212 lines
5.1 KiB
Markdown
212 lines
5.1 KiB
Markdown
# 反向 WebSocket 负载均衡配置
|
||
|
||
## 功能特性
|
||
|
||
### 1. 负载均衡
|
||
|
||
当有多个前端(NapCat等)连接到反向WebSocket服务端时,系统会自动进行负载均衡:
|
||
|
||
- **自动选择负载最低的客户端**:API调用时会自动选择负载最低的健康客户端
|
||
- **健康检查**:系统会记录每个客户端的最后活动时间,只选择最近30秒内有活动的客户端
|
||
- **负载计数**:每个客户端的消息处理次数会被记录,用于负载均衡计算
|
||
|
||
### 2. 防重复发送
|
||
|
||
系统实现了多层防重复机制:
|
||
|
||
- **事件ID检查**:通过事件ID(`id`、`post_id`或`time`)识别重复事件
|
||
- **消息锁机制**:使用异步锁防止同一消息被并发处理
|
||
- **双重检查**:在锁内再次检查是否重复,防止并发竞争条件
|
||
- **自动清理**:定期清理过期的事件ID和消息锁(默认60秒和300秒)
|
||
|
||
### 3. 工作原理
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ Frontend │
|
||
│ (NapCat) │
|
||
└──────┬──────┘
|
||
│
|
||
│ WebSocket
|
||
│
|
||
┌──────▼──────┐
|
||
│ │
|
||
│ ReverseWS │ ←── 负载均衡 + 防重复
|
||
│ Manager │
|
||
│ │
|
||
└──────┬──────┘
|
||
│
|
||
│ 处理事件
|
||
│
|
||
┌──────▼──────┐
|
||
│ Command │
|
||
│ Manager │
|
||
│ │
|
||
└─────────────┘
|
||
```
|
||
|
||
## 配置说明
|
||
|
||
在 `config.toml` 中配置:
|
||
|
||
```toml
|
||
[reverse_ws]
|
||
enabled = true # 启用反向WebSocket
|
||
host = "0.0.0.0" # 监听地址
|
||
port = 3002 # 监听端口
|
||
token = "" # 访问令牌(可选)
|
||
```
|
||
|
||
## 使用方法
|
||
|
||
### 启动配置
|
||
|
||
1. 在 `config.toml` 中设置 `enabled = true`
|
||
2. 确保防火墙允许指定端口的连接
|
||
3. 启动机器人服务
|
||
|
||
### 前端配置
|
||
|
||
在 NapCat 等前端配置中,将 WebSocket 连接地址改为:
|
||
|
||
```
|
||
ws://your-server-ip:3002
|
||
```
|
||
|
||
多个前端可以连接到同一个地址,系统会自动进行负载均衡。
|
||
|
||
## API 调用
|
||
|
||
### 使用负载均衡(推荐)
|
||
|
||
```python
|
||
from core.managers import reverse_ws_manager
|
||
|
||
# 自动选择负载最低的健康客户端
|
||
response = await reverse_ws_manager.call_api(
|
||
action="send_group_msg",
|
||
params={
|
||
"group_id": 123456,
|
||
"message": "Hello"
|
||
},
|
||
use_load_balance=True # 默认为 True
|
||
)
|
||
```
|
||
|
||
### 指定客户端
|
||
|
||
```python
|
||
# 向特定客户端发送
|
||
response = await reverse_ws_manager.call_api(
|
||
action="send_group_msg",
|
||
params={
|
||
"group_id": 123456,
|
||
"message": "Hello"
|
||
},
|
||
client_id="specific-client-id",
|
||
use_load_balance=False
|
||
)
|
||
```
|
||
|
||
### 获取客户端信息
|
||
|
||
```python
|
||
# 获取所有连接的客户端
|
||
clients = reverse_ws_manager.get_connected_clients()
|
||
|
||
# 获取健康的客户端(最近30秒有活动)
|
||
healthy = reverse_ws_manager.get_healthy_clients()
|
||
|
||
# 获取负载最低的客户端
|
||
least_load = reverse_ws_manager.get_client_with_least_load()
|
||
```
|
||
|
||
## 负载均衡策略
|
||
|
||
系统采用以下策略选择客户端:
|
||
|
||
1. **健康检查**:只选择最近30秒内有活动的客户端
|
||
2. **负载计数**:在健康客户端中选择负载最低的
|
||
3. **自动切换**:如果负载最低的客户端不健康,自动选择下一个
|
||
|
||
## 防重复机制
|
||
|
||
### 事件ID检查
|
||
|
||
系统通过以下方式识别事件:
|
||
|
||
- 优先使用 `id` 字段
|
||
- 其次使用 `post_id` 字段
|
||
- 最后使用 `time` 字段
|
||
|
||
### 消息锁
|
||
|
||
消息处理使用异步锁,防止并发重复处理:
|
||
|
||
```python
|
||
async with self._get_message_lock(message_key):
|
||
# 处理消息
|
||
await matcher.handle_event(None, event)
|
||
```
|
||
|
||
### 自动清理
|
||
|
||
系统每10秒清理一次过期数据:
|
||
|
||
- 事件ID保留时间:60秒
|
||
- 消息锁保留时间:300秒
|
||
|
||
## 监控和调试
|
||
|
||
### 查看客户端状态
|
||
|
||
```python
|
||
# 查看所有客户端
|
||
print("所有客户端:", reverse_ws_manager.get_connected_clients())
|
||
|
||
# 查看健康客户端
|
||
print("健康客户端:", reverse_ws_manager.get_healthy_clients())
|
||
|
||
# 查看负载情况
|
||
print("客户端负载:", reverse_ws_manager._client_load)
|
||
|
||
# 查看健康时间
|
||
print("客户端健康时间:", reverse_ws_manager._client_health)
|
||
```
|
||
|
||
### 日志输出
|
||
|
||
系统会输出以下日志:
|
||
|
||
- 客户端连接/断开
|
||
- 检测到重复事件
|
||
- 负载均衡选择
|
||
- API调用结果
|
||
|
||
## 最佳实践
|
||
|
||
1. **多前端部署**:建议部署2-3个前端实例进行负载均衡
|
||
2. **健康检查**:定期检查前端连接状态
|
||
3. **监控日志**:关注重复事件日志,排查网络问题
|
||
4. **合理设置TTL**:根据消息频率调整事件ID保留时间
|
||
|
||
## 故障排查
|
||
|
||
### 问题:消息重复处理
|
||
|
||
**原因**:网络延迟导致前端重复发送
|
||
|
||
**解决**:检查事件ID是否正确设置,系统已自动处理
|
||
|
||
### 问题:API调用超时
|
||
|
||
**原因**:选择的客户端不健康或网络问题
|
||
|
||
**解决**:系统会自动切换到其他健康客户端
|
||
|
||
### 问题:所有客户端都不健康
|
||
|
||
**原因**:前端断开连接或网络问题
|
||
|
||
**解决**:检查前端连接状态和网络连接
|