Files
qiming/qimingclaw/crates/qiming-mcp-stdio-proxy/docs/heartbeat-and-retry.md

58 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 心跳与重试机制设计 (qiming-mcp-stdio-proxy)
## 1. 背景与问题
目前 `qiming-mcp-stdio-proxy` 缺乏针对其传输层(特别是 `sse``streamable` 远程连接的健壮的心跳Keep-Alive和透明重试机制。如果后端的 MCP 服务器崩溃或网络断开,依赖代理的下游 Agent 会遇到 `stdio` 管道断裂或请求挂起的问题。
我们需要一个具有弹性的代理层:
1. 主动监控上游连接的健康状况(使用 Ping 等请求)。
2. 如果连接断开,透明地重连并重新映射传输层。
3. 对下游的 Agent仅通过标准 stdio 通信)屏蔽这些临时故障,有效创建一个“永远在线”的代理抽象。
## 2. 核心功能与要求
### 2.1 心跳 (Keep-Alive)
- **间隔**: 默认 20 秒 (`--ping-interval`)。
- **超时**: 默认 5 秒 (`--ping-timeout`)。
- **方式**: 发送 MCP 的 JSON-RPC `ping` 请求进行健康检查。
- **失败阈值**: 连续 3 次健康检查失败。
### 2.2 重连与重试逻辑
- 当连接被认定为不健康(连续 3 次失败或传输层触发 `onclose`/`onerror`)时:
1. 状态变更为 `RECONNECTING` (重连中)。在重连期间到达的 MCP 请求会进入内部队列进行缓冲,代理本身**绝不能崩溃**。
2. 代理启动对上游服务的重连(重新 spawn 标准子进程,或重新建立 SSE/Streamable HTTP 连接)。
3. 重连成功后,代理将把内部的 `Transport` 重新映射到新的连接,并自动刷出之前排队的请求。
4. 下游 Agent 与代理之间的 `stdio` 连接在整个过程中保持完好无损。
## 3. 架构设计
### 3.1 弹性代理传输层 (ResilientTransportWrapper)
我们使用 `ResilientTransportWrapper` 将底层的连接进行封装。这个 Wrapper 向上层环境暴露标准稳定的 `Transport` 接口,但内部动态管理和更替实际的 SSE/Streamable/Stdio 传输实例。
```typescript
class ResilientTransportWrapper implements Transport {
// 实现 MCP Transport 接口
// 内部管理实际的连接 (activeTransport)
// 包含断开重连逻辑、心跳检测机制和消息排队发送队列
}
```
### 3.2 内部实现细节
1. **连接建立**: 初始化时通过外部传入的 `connectParams` 工厂函数创建底层的 Transport 连接。
2. **心跳定时器**: 每隔固定时间(例如 20 秒),向 `activeTransport` 发送原生的 JSON-RPC `ping` 请求。如果在发送期间抛错或传输直接断开,则累加连续失败计数。
3. **断开拦截**: 拦截 `activeTransport``onclose``onerror` 事件,并触发内部重连,防止其向上冒泡直接中止下游的 stdio 代理进程。
4. **请求排队**: 当正处于重连状态时,由于暂时没有可用的底层发送通道,通过外层 `send(message)` 收到的任何请求都会进入一个有容量限制(默认 100的队列中。新的底层连接建立成功后会迅速重放flush发送队列的所有请求。
5. **多模式支持**: 这个逻辑被集中继承到了 `modes/convert.ts` (独立服务转换模式) 及 `bridge.ts` (`PersistentMcpBridge` 持久化管理桥接) 内部,以实现对不同形式请求的通用重连保护。
## 4. 命令行及参数配置
新增了控制心跳频次的参数选项支持,可以通过启动命令或在配置文件内声明:
- `--ping-interval <毫秒>`: 发送心跳 Ping 的时间间隔(如果不指定,默认为 20000 即 20 秒)。
- `--ping-timeout <毫秒>`: 心跳请求超时判断(如果不指定,默认为 5000 即 5 秒)。