# Control Plane gRPC API ## 1. 契约范围 Proto 源文件位于 `api/proto/controlplane/v1/controlplane.proto`,包含两项 内部服务: - `WorkerControlPlane`:Worker 注册、Snapshot/Delta 分发、ACK、运行态与结果 批量上报。 - `CheckerControlPlane`:健康检查任务流和 Observation 批量上报。 该协议不承载 Client 的独占提取,也没有 extraction lease/release。Proxy 的 `AVAILABLE -> EXTRACTED` 只在 Controller 调用的 Redis 原子操作中完成。 ## 2. Worker 会话 ```mermaid sequenceDiagram participant W as Gateway Worker participant C as Controller W->>C: RegisterWorker(worker, instance, zone) C-->>W: session + ownershipEpoch + maxStaleAge W->>C: WatchSnapshots(lastVersion, checksum) C-->>W: full WorkerSnapshot W->>W: validate + build immutable snapshot W->>W: atomic swap W->>C: AcknowledgeSnapshot(version, epoch, checksum) loop bounded interval W->>C: ReportRuntime(active, reserved, draining) W->>C: ReportOutcomes(batch sequence) end ``` `worker_id` 是逻辑节点,`instance_id` 区分进程重启,`session_id` 防止旧进程 继续上报。所有权 `epoch` 小于 Controller 当前值的数据必须拒绝。 ## 3. Snapshot 与 Delta 完整 Snapshot 包含: - 单调 `version`、`ownership_epoch`、生成时间和有效期。 - 对该 Worker 可见的有序 Routing。 - 仅归该 Worker 所有的 Proxy、每个 Proxy 的容量、硬过期时间 `expires_at` 和停止新分配的 `usable_until`。 - 内容 `checksum`。 `usable_until = expires_at - allocationSafetyMargin`。Worker 必须以 `usable_until` 作为最后可分配时刻;达到该时间后即使尚未到 `expires_at`, 也不得再为新请求选择该 Proxy。 Delta 声明 `base_version`。Worker 只有在本地版本恰好等于 base 且 checksum 验证成功时才能应用;否则丢弃 Delta 并请求完整 Snapshot。构建在后台完成, 热路径只读取一次原子指针。 超过 `max_stale_age` 仍未取得有效快照时,Worker 停止接收新流量并排空已有 请求。控制面中断不能让 Worker 查询 PostgreSQL 或 Redis 补偿热路径。 ## 4. 所有权与 Drain 同一 Proxy 同时只归一个 Worker。Controller 回收用于独占提取的 Proxy 时: 1. 新 Snapshot 标记或移除该 Proxy,使 Worker 停止新预留。 2. Worker 上报 `draining=true` 以及 Active/Reserved。 3. 两个计数都归零后 Controller 清除所有权。 4. 无所有权 Proxy 才能进入 Distribution 的 Redis 原子提取操作。 Worker 崩溃时必须等待所有权 epoch/有效期失效后再转移,避免双主。Proto 中 `ReportRuntimeResponse.revoke_proxy_ids` 是加速 Drain 的控制信号,不绕过 Snapshot 版本和 Redis 中的权威所有权状态。 ## 5. Outcome 上报 Outcome 按 Worker 单调 `sequence` 批量上报。Controller 返回已接受的最大序号, 从而支持有限重试和去重。阶段区分: - `DIAL`:连接 Proxy 地址失败。 - `PROXY_HANDSHAKE`:HTTP CONNECT 或 SOCKS 握手失败。 - `RESPONSE_HEADERS`:目标响应头前失败。 - `TUNNEL`:隧道建立后结束或失败。 Outcome 是 Observation,不直接让 Worker 修改 Redis 活动池状态,也不创建 PostgreSQL Proxy 明细。异步上报队列必须有界;队列满时丢弃低价值样本并计 指标,不能反压 Gateway 热路径。 ## 6. Checker 任务 Checker 注册自身最大并发与支持层级,Controller 发送有 deadline 的任务: - `BASIC`:基础连通和协议握手。 - `EGRESS`:出口身份与匿名性。 - `TARGET`:针对 Routing/目标组的可达性。 Checker 只返回 `HealthObservation`。Controller reducer 按 Proxy、检查层级和 Routing 决定 AVAILABLE、SUSPECT 或 UNHEALTHY,并更新 Redis 活动池,避免 多个 Checker 并发写状态。 ## 7. 兼容与演进 - Proto 字段号一旦发布不得复用。 - 删除字段使用 `reserved` 保留名称和编号。 - 新枚举值必须让旧接收方按 UNSPECIFIED/拒绝策略处理。 - Worker 注册携带 `supported_protocol_version`,不兼容时注册失败而不是静默 降级。 - Stream 断开后使用带 jitter 的有界指数退避,禁止紧密重连。 ## 8. 传输安全 集群环境使用 mTLS,证书身份绑定 Worker/Checker 类型和环境。服务端校验 消息中的逻辑 ID 与证书授权一致,设置单消息大小、流持续时间、并发 Stream 和上报批次上限。`secret_ref` 是受控引用,不在 Proto 中传播真实密码。