mirror of
https://github.com/zhouxiaoka/autoclip.git
synced 2026-05-06 22:13:00 +08:00
4.3 KiB
4.3 KiB
WebSocket问题修复总结
问题分析
根据日志分析,发现了三个主要问题:
- 自动断开重连:每10秒左右就有断开重连,说明缺少心跳机制
- 重复日志:每10秒出现"新增0,移除0,未变8"的重复日志
- 进度跳跃:前端从0%直接跳到100%,缺少快照机制
修复方案
1. 修复WebSocket自动断开重连问题 ✅
问题根因:缺少心跳机制,代理/浏览器在10~60s内回收"静默连接"
解决方案:
- 前端每25秒发送一次ping心跳
- 后端收到ping后立即回复pong
- 前端5秒内没收到pong就主动重连
- 添加指数退避重连机制
修改文件:
frontend/src/hooks/useWebSocket.ts:添加心跳机制和重连逻辑
2. 修复重复日志问题 ✅
问题根因:前端频繁调用syncSubscriptions,后端每次都记录INFO日志
解决方案:
- 前端添加300ms防抖机制
- 后端只在有实际变化时才记录INFO日志
- 无变化的同步降为DEBUG级别
修改文件:
frontend/src/hooks/useWebSocket.ts:添加防抖机制backend/services/websocket_gateway_service.py:优化日志级别
3. 实现进度快照机制 ✅
问题根因:前端错过中间的WebSocket推送,缺少"最新快照/补发机制"
解决方案:
- 后端每次发布进度时同时保存快照到Redis Hash
- 用户订阅时立即发送最新快照
- 快照标记为
snapshot: true,前端可识别
修改文件:
backend/services/progress_event_service.py:添加快照存储和获取backend/services/websocket_gateway_service.py:订阅时发送快照
4. 修复asyncio.run()错误 ✅
问题根因:在已运行的事件循环中调用asyncio.run()
解决方案:
- 使用
asyncio.get_running_loop()和create_task() - 避免在async上下文中创建新的事件循环
修改文件:
backend/api/v1/bilibili.py:修复事件循环冲突
5. 优化WebSocket发送机制 ✅
问题根因:直接调用websocket.send_text()可能导致close后send错误
解决方案:
- 所有消息发送都通过队列机制
- 避免在连接关闭后发送消息
修改文件:
backend/core/websocket_manager.py:统一使用队列发送
技术细节
心跳机制实现
// 前端心跳
const HEARTBEAT_INTERVAL = 25000; // 25秒
const HEARTBEAT_TIMEOUT = 5000; // 5秒超时
// 发送ping
globalWs.send(JSON.stringify({ type: 'ping' }));
// 处理pong
if (data.type === 'pong') {
clearTimeout(heartbeatTimeout);
}
快照机制实现
# 发布进度时保存快照
snapshot_key = f"progress:last:{channel}"
await redis_client.hset(snapshot_key, mapping=filtered_dict)
# 订阅时发送快照
snapshot = await progress_event_service.get_task_snapshot(task_id)
if snapshot:
snapshot_message = {**snapshot, "snapshot": True}
await manager.send_personal_message(snapshot_message, user_id)
防抖机制实现
// 300ms防抖
if (syncDebounceTimeout) {
clearTimeout(syncDebounceTimeout);
}
syncDebounceTimeout = window.setTimeout(() => {
// 发送同步请求
}, SYNC_DEBOUNCE_DELAY);
测试验证
创建了完整的测试脚本验证修复效果:
- ✅ Redis连接测试
- ✅ 进度快照测试
- ✅ WebSocket网关测试
所有测试通过,修复效果良好。
预期效果
修复后应该实现:
- 稳定的WebSocket连接:不再频繁断开重连
- 清晰的日志输出:减少重复日志,只在有变化时记录
- 平滑的进度显示:前端能立即看到最新进度,不会从0%直接跳到100%
- 稳定的系统运行:不再出现asyncio事件循环错误
- 可靠的消息传递:避免close后send的错误
使用建议
- 监控日志:观察是否还有频繁的断开重连
- 测试进度:启动一个处理任务,观察前端进度是否平滑显示
- 检查快照:刷新页面后应该立即显示最新进度
- 验证心跳:在浏览器开发者工具中可以看到ping/pong消息
后续优化
- Redis Stream:可考虑使用Redis Stream实现更完整的消息历史
- 连接池:优化Redis连接管理
- 监控指标:添加WebSocket连接数和消息统计
- 错误恢复:增强网络异常时的自动恢复能力