feat: 添加状态监控插件和Redis原子操作支持

- 新增 `/status` 指令,展示机器人运行状态和系统指标
- 实现Redis Lua脚本支持原子化计数器操作
- 添加消息收发统计功能
- 完善文档,包括插件开发和性能优化指南
- 重构WebSocket连接池,增加健康检查机制
- 移除旧版编译脚本,优化项目结构
This commit is contained in:
2026-01-23 15:54:45 +08:00
parent 489dd8c77d
commit d458413e4b
28 changed files with 1529 additions and 1177 deletions

View File

@@ -119,4 +119,22 @@ python setup_mypyc.py
- **当前状态**:为了确保稳定性,`setup_mypyc.py` 脚本**默认不编译** `models/events/` 目录下的事件模型文件。这些文件虽然也被频繁使用,但它们的结构相对复杂,与 `Mypyc` 的兼容性问题仍在探索中。
- **未来展望**:我们会持续关注 `Mypyc` 的更新,当其对 `dataclass` 的支持得到改善后,会重新尝试将事件模型加入编译列表,以实现极致的性能。
## 7. 健壮的 WebSocket 连接池
### 痛点
在高并发或网络不稳定的情况下,单个 WebSocket 连接可能会因为各种原因(如超时、服务器重启、网络波动)而中断或变得不可靠。如果框架依赖于单一的、不稳定的连接,会导致 API 调用频繁失败,甚至整个机器人无响应。
### 解决方案
`NeoBot` 实现了一个健壮的 `WebSocket 连接池` (`core/ws_pool.py`),它不仅管理多个连接,还具备智能的健康检查和恢复机制。
- **多连接管理**: 启动时会建立一个包含多个 WebSocket 连接的池API 调用会被分发到这些连接上,实现负载均衡。
- **自动健康检查**: 连接池会定期对池中的每个连接进行健康检查(发送 `get_status` 心跳包)。如果一个连接在规定时间内没有响应,它会被标记为“不健康”。
- **故障转移与恢复**: 当一个 API 调用需要使用连接时,连接池会自动选择一个“健康”的连接。如果所有连接都不健康,它会尝试重新建立新的连接,直到成功为止。
- **无感切换**: 对于上层调用者(如插件开发者)来说,这一切都是透明的。你只需要正常调用 `bot.call_api()`,连接池会在底层处理好所有的连接问题。
### 收益
- **高可用性**: 即使部分连接失效,机器人依然可以通过健康的连接继续提供服务,大大减少了因网络问题导致的停机时间。
- **高并发性能**: 通过连接池,多个 API 请求可以并行地通过不同的连接发送,提高了在高并发场景下的吞吐量。
- **自动恢复**: 无需手动重启机器人,连接池能够自动从网络故障中恢复,增强了系统的稳定性和无人值守能力。
通过这种方式,我们在保证核心模块性能的同时,也维持了项目的稳定性和可维护性。

View File

@@ -132,4 +132,43 @@ if await permission_manager.check_permission(user_id, Permission.ADMIN):
## 总结
通过以文件为权威数据源、Redis 为缓存层的设计结合原子操作机制NEO Bot 的权限管理系统在保证数据可靠性的同时,提供了高性能的访问能力。这种设计既满足了数据一致性的要求,又兼顾了系统性能的需求。
通过以文件为权威数据源、Redis 为缓存层的设计结合原子操作机制NEO Bot 的权限管理系统在保证数据可靠性的同时,提供了高性能的访问能力。这种设计既满足了数据一致性的要求,又兼顾了系统性能的需求。
## 扩展应用:指令调用统计
除了权限管理,原子操作的思想也应用在了指令调用统计中,但实现方式更为高效。
### 痛点
如果每次调用指令都执行 `GET` -> `(本地+1)` -> `SET` 的流程在高并发下会产生“竞争条件”Race Condition导致计数不准确。例如两个请求同时读取到计数值 10各自加一后都写回 11而正确的结果应该是 12。呵呵其实是看到zmd事件紧急添加的功能
### 解决方案Lua 脚本
`NeoBot` 使用 Redis 的 `EVAL` 命令执行一个 Lua 脚本来实现原子化的计数器。
```lua
-- Lua 脚本 (简化版)
local current = redis.call('HGET', KEYS[1], ARGV[1])
local count = tonumber(current) or 0
count = count + 1
redis.call('HSET', KEYS[1], ARGV[1], count)
return count
```
- **原子性**: Redis 会保证整个 Lua 脚本的执行是原子性的,执行期间不会被其他命令打断。
- **高效性**: 将多个操作(读取、计算、写入)在 Redis 服务器端一次性完成,减少了网络往返的开销。
### 核心实现
`RedisManager` 中,我们封装了 `execute_lua_script` 方法,使得在 Python 中调用 Lua 脚本变得非常简单。
```python
# Python 调用示例
await redis_manager.execute_lua_script(
"atomic_hincrby.lua",
keys=["neobot:stats:command_usage"],
args=[command_name]
)
```
### 收益
- **数据准确性**: 彻底杜绝了高并发下的计数错误问题。
- **高性能**: 相比于传统的“读取-修改-写入”模式,使用 Lua 脚本能显著提升性能,特别是在指令调用这种高频场景下。
- **可扩展性**: 这种模式可以轻松应用于其他需要原子操作的场景,如频率限制、资源池管理等。