From b8f51041672089616f2c5b4cc5e56f36e8125786 Mon Sep 17 00:00:00 2001 From: youfak Date: Thu, 30 Jul 2026 19:47:10 +0800 Subject: [PATCH] docs: record provider lifecycle delivery --- README.md | 3 +- docs/adr/006-postgresql-admin-state.md | 11 +++++-- docs/api/admin.md | 20 +++++++++++-- docs/configuration/reference.md | 38 +++++++++++++++++++++---- docs/design/architecture.md | 26 ++++++++++++++++- docs/development/implementation-plan.md | 25 +++++++++++----- docs/operations/production-readiness.md | 3 +- docs/operations/runbook.md | 15 +++++++--- docs/requirements/traceability.md | 6 ++-- docs/testing/strategy.md | 13 +++++++-- docs/testing/test-strategy.md | 2 +- 11 files changed, 131 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d45d812..1bdbb60 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Windows PowerShell 可运行: 2. Proxy 容量使用 `Reserved -> Active` 原子转换,禁止超卖。 3. Distribution 成功时原子执行 `AVAILABLE -> EXTRACTED`,不提供 Lease、 Release 或 Renewal。 -4. `pool.maxSize` 是当前未提取库存上限;`fetch.maxTotal` 是累计获取额度。 +4. `pool.maxSize` 是当前未提取库存硬上限;`fetch.maxTotal` 是 Redis generation + 内的累计获取停止阈值。 5. CONNECT 向客户端提交 200 后不透明重放。 6. 公开监听必须有认证或 CIDR 访问保护。 diff --git a/docs/adr/006-postgresql-admin-state.md b/docs/adr/006-postgresql-admin-state.md index 8afca90..4687f26 100644 --- a/docs/adr/006-postgresql-admin-state.md +++ b/docs/adr/006-postgresql-admin-state.md @@ -70,9 +70,14 @@ Outbox。状态变化、审计和 Outbox 在同一事务提交。 ### 配置修订 -配置提交只保存管理面恢复所需的非敏感事实:配置版本、SHA-256 校验和、来源、 -Upstream 启用状态和 Routing 候选/当前选择。已解析 Secret、Provider Token、 -Proxy 凭据和完整运行时对象不进入 PostgreSQL。 +配置提交只保存管理面恢复所需的非敏感事实:配置版本、完整已解析配置的 +HMAC-SHA-256 指纹、来源、Upstream 启用状态和 Routing 候选/当前选择。HMAC 使用 +独立外部高熵密钥,覆盖 Secret 轮换以驱动多副本收敛,同时避免普通摘要成为 +低熵 Secret 的离线校验器。HMAC 密钥、已解析 Secret、Provider Token、Proxy +凭据、配置正文和完整运行时对象均不进入 PostgreSQL。 + +配置发布携带事务返回的全局 revision。本地 `config.Store` 只接受严格递增 +revision,因此并发提交或 Supervisor 同步的迟到旧版本不能覆盖较新运行配置。 配置重载以一个事务替换管理快照。新 Routing 的当前 Upstream 必须属于其候选集, 所有引用的 Upstream 必须存在,名称与列表必须非空且唯一。校验失败发生在事务前, diff --git a/docs/api/admin.md b/docs/api/admin.md index cc467b9..4aef0f6 100644 --- a/docs/api/admin.md +++ b/docs/api/admin.md @@ -39,10 +39,24 @@ Status 以一个权威管理快照决定 Upstream 集合和 Enabled 状态,只 1. `FileConfigurationLoader` 通过 `config.LoadResolved` 严格解析、解析 Secret 引用 并完成全量校验。 -2. 从脱敏管理投影计算版本与校验和;Secret 值及其可验证摘要不进入管理状态。 +2. 使用独立外部密钥对完整已解析配置计算 HMAC-SHA-256 指纹;PostgreSQL 只保存 + 不透明 HMAC,不保存密钥、配置正文或 Secret 明文,因此 URL、模板和 Secret + 轮换都会产生新版本,也不能借数据库摘要离线猜测低熵 Secret。 3. 在同一 `adminstate` mutation 中提交配置修订、管理状态、审计和 Outbox。 -4. 提交成功后由 `config.Store` 一次原子指针交换发布完整运行配置;提交失败时旧 - 配置保持不变。幂等重放仍执行发布,以修复进程本地状态。 +4. 提交成功后由 `config.Store` 按 PostgreSQL revision 原子发布完整运行配置; + Store 只接受严格递增 revision,提交失败或迟到旧 revision 不覆盖当前配置。 + 幂等重放仅在本地 revision 落后时修复进程状态。 +5. Provider Supervisor 在提交前构造预检所有启用 Upstream;发布后按新配置取消、 + 替换或新增 Runtime。enable 同样在管理状态 mutation 前预检目标 Runtime。 +6. 其他 Controller 每秒比较本地指纹与 PostgreSQL 权威指纹;所有副本必须使用 + 相同 `PROXY_POOL_CONFIG_FINGERPRINT_KEY`。共享配置源已同步时严格重载、预检 + 并按 revision 发布,源尚未同步时停止旧 Provider Runtime,禁止旧 URL/Secret + 在换主后继续调用。 + +disable 成功后会立即通知 Supervisor 取消目标 Runtime;每秒一次的权威状态对账 +用于修复进程内通知丢失。已取得的分布式 Permit 仍按幂等、保守规则完成结算。 +PostgreSQL 瞬时读取失败不会终止 Controller 或取消当前 Provider Runtime; +Supervisor 保留 last-known 状态并在下一周期重试。 主配置或 Secret 文件 I/O 故障归类为 503;语法、未知字段、引用和语义校验失败 归类为 422。请求取消和截止时间保持原始上下文错误,不误报为配置错误。 diff --git a/docs/configuration/reference.md b/docs/configuration/reference.md index 7f73b01..386dead 100644 --- a/docs/configuration/reference.md +++ b/docs/configuration/reference.md @@ -16,10 +16,13 @@ Controller 入口已实现,源码运行方式为: go run ./cmd/proxy-controller -config CONFIG_FILE ``` -配置路径优先使用 `-config`,未提供时读取 `PROXY_POOL_CONFIG`。该入口已装配 +配置路径优先使用 `-config`,未提供时读取 `PROXY_POOL_CONFIG`。启用 Admin 时还 +必须设置 `PROXY_POOL_CONFIG_FINGERPRINT_KEY`,值为至少 32 字节的独立高熵密钥; +所有 Controller 副本必须一致,且该密钥不得放入 YAML 或 PostgreSQL。该入口已装配 PostgreSQL 管理面迁移、Redis 活动池、Distribution/Admin 独立监听与优雅停机; Controller Metrics 独立监听、`/livez`、`/readyz` 和基础 Prometheus 运行时指标; -Provider 自动补池、业务指标和完整部署拓扑仍在后续实施范围。 +Provider 自动补池、分布式配额、动态重载和 Admin 低基数统计已装配。完整 Gateway、 +Checker、Worker 控制面与代表性负载验证仍在后续实施范围。 所有时间值使用 Go duration,例如 `500ms`、`30s`、`5m`。示例中的 `${TOKEN}`、`${PASSWORD}`、`${POSTGRES_URL}` 等由加载器从同名环境变量 @@ -312,11 +315,30 @@ proxyAuth: - `pool.maxSize`:当前系统维护且尚未 EXTRACTED 的 Proxy 硬上限,包括 FETCHED、CHECKING、AVAILABLE、SUSPECT、DRAINING 和 pending expected。 -- `fetch.maxTotal`:当前运行或计费周期内,从 Provider 成功获取的累计上限; - `0` 表示不设置累计上限。 +- `fetch.maxTotal`:当前 Redis generation 内的累计获取停止阈值;`0` 表示不设置。 + Redis 在调用前原子校验 `fetched total + pending expected + expected`,并在达到 + 阈值后停止发起新调用。 `fetch.maxTotal` 不得小于 `pool.maxSize`。提取一个 Proxy 会释放当前库存位置, -但不会恢复累计获取额度。 +但不会恢复累计获取额度。Provider 调用结果不确定、响应无法解析或 Permit 过期时, +系统按 `estimatedIPsPerCall` 保守记账,避免故障或换主造成额度低估。Redis 全量 +状态丢失会创建新 generation,因此需要由外部计费系统提供跨 generation 的长期额度。 + +`estimatedIPsPerCall` 是预留估值,不是通用的 Provider 响应硬限制。如果某次实际 +合法返回量超过估值,系统只保留本地池容量允许的数量,但累计账本按实际合法数量 +记账并停止后续调用;该次可能越过停止阈值。需要绝对硬上限时,必须同时在 Provider +请求参数中配置供应商支持的批量上限,并保证其不超过剩余额度。 + +当前实现限制单个 `pool.maxSize <= 1,000,000`、配置内 Upstream 总数不超过 +`4,096`,并要求单代理并发、Refill 双水位、理论总槽位及其他传入 Redis Lua 的 +累计/并发计数不超过 `2^53-1`。这些边界在配置加载和 Admin reload 提交前校验, +不会等到 Provider Runtime 启动后才失败。 + +`proxyAuth.type: response` 的用户名/密码是 Parser 到 Redis Activity Adapter 之间的 +临时凭据。每次 Parser handoff 使用独立、幂等释放的 lease,避免并发 Fetch 互相 +删除或轮换版本覆盖;成功复制到 TTL 活动记录、候选被截断或解析失败后都会释放。 +内存 lease 上限按所有配置 Upstream 的 `pool.maxSize * fetch.maxInFlight` 汇总, +配置 reload 只提高上限,不预分配对应内存。 ### 7.3 Fetch 限制 @@ -376,6 +398,12 @@ PostgreSQL 只保存配置版本、Upstream/Routing 管理状态、Admin 审计 PostgreSQL 故障本身不应使 Redis 中可完成的 Extract 返回 `503`。Metrics 标签 禁止 Proxy IP、Client ID、Session、完整 URL 和 Request ID。 +启用 Admin 的多 Controller 部署必须让所有副本读取同一版本化配置源、Secret +版本和 `PROXY_POOL_CONFIG_FINGERPRINT_KEY`。Supervisor 每秒比较本地完整配置的 +HMAC-SHA-256 与 PostgreSQL 权威值:管理状态暂时不可读时沿用 last-known +Runtime;指纹已更新但本地源尚未同步时停止旧 Provider,待源匹配并通过预检后 +按全局 revision 恢复,避免旧凭据换主或迟到旧配置回写。 + Metrics 启用时 `listen` 必须是合法 `host:port`。该入口固定提供 `/livez`、 `/readyz` 和 `/metrics`,不复用 Distribution/Admin 的认证边界;外部访问必须由 网络策略限制。当前 `/metrics` 已包含 Go/进程基础指标,Provider、提取和容量等 diff --git a/docs/design/architecture.md b/docs/design/architecture.md index 5eff276..956ddd4 100644 --- a/docs/design/architecture.md +++ b/docs/design/architecture.md @@ -253,6 +253,24 @@ flowchart TD fail-closed,不回退为本地 Leader。补池使用 minimum/target 双水位迟滞,库存 复核期间若仍有 pending Fetch,则等待下一轮再同步 Managed,避免重复计数。 +Controller Bootstrap 通过 `Provider Supervisor` 按权威配置和 PostgreSQL 管理状态 +维护每个 Upstream 的独立 `UpstreamRuntime`,再与 HTTP Runtime 通过公用 lifecycle +Group 联动启动、取消和等待。Admin disable 会通知 Supervisor 取消对应 Runtime; +reload 在提交前预检新 Runtime,并在发布后逐个取消、替换或新增。低频对账用于修复 +丢失通知。每个 Leader 任期重新创建本地补池预算与合并信号;Redis 是 +requestInterval、maxInFlight 和 maxTotal 的唯一分布式裁决者。本地预算只负责 +pool.maxSize。 + +maxTotal 使用 Redis generation 内的累计值与 pending expected 原子预留。调用结果 +不确定、解析失败或结算丢失时按 expected 保守记账,换主后旧 Permit 仍可幂等结算。 +如果 Provider 单次实际返回量超过 `estimatedIPsPerCall`,账本按实际合法数量记账并 +停止后续调用,但该次可能越过停止阈值;严格硬封顶需要 Provider API 支持可控批量。 + +响应中携带的代理凭据先进入有界内存凭据表,Redis Activity Adapter 复制凭据材料 +进入 TTL 活动记录后立即按版本 fence 释放临时引用;解析中途失败也会回收已写引用。 +因此短 TTL、持续轮换的新代理地址不会耗尽启动时的凭据容量。Provider 结果只记录 +每个 Upstream 的低基数 Empty/Error 计数,不保留响应体、代理地址或错误对象。 + 补池读取 `pool.InventoryReader` 返回的权威 `Managed` 与 `AvailableSlots`,不使用 AVAILABLE Proxy 数量乘固定并发的近似值。Available Slots 同时计入 Proxy 状态、 TTL safety margin、MaxConcurrency、Worker Active/Reserved 和当前 ownership; @@ -419,6 +437,12 @@ flowchart LR - Routing 立即对新请求生效;旧请求持有旧 Snapshot 完成。 - 修改 API 地址或凭据版本会重建 Provider Adapter,但不会把错误计成 Empty。 - 新配置任何校验失败时,保留旧版本并报告完整错误。 +- 多 Controller 以 PostgreSQL 中的 HMAC-SHA-256 完整配置指纹检测修订;HMAC + 密钥由外部 Secret 注入且所有副本一致。副本从共享配置源读取相同 revision, + 预检后通过单调 revision 栅栏原子发布。权威指纹已变化但本地源仍旧时,旧 + Provider fail-closed 停止,避免旧 URL/Secret 在 Leader 换主后继续使用。 +- PostgreSQL 瞬时读取失败时沿用 last-known Provider Runtime 并重试,不连带终止 + Distribution、Admin 或 Metrics。 ## 15. 安全 @@ -479,7 +503,7 @@ CPU、内存、网络、Go 版本、配置和上游响应模型下测得。 | Provider 超时/500 | 计 Error、退避;不计 Empty,不影响已有 Proxy | | Provider 合法空响应 | Empty++;达到阈值触发相关 Routing 原子切换 | | Redis 不可用 | Gateway 暂用未过期快照;停止 Fetch 入池、Extract 和所有权变更 | -| PostgreSQL 不可用 | Gateway 与 Redis Extract 不受影响;停止管理状态变更和 Admin 审计 | +| PostgreSQL 不可用 | Gateway 与 Redis Extract 不受影响;停止管理写入,Provider 沿用 last-known 状态并重试 | | Controller 断线 | Worker 在 maxStaleAge 内继续;超限拒绝新流量并排空 | | Worker 崩溃 | 所有权租约过期后重新分配;期间不双重所有 | | Checker 积压 | 降低普通复检频率,优先新 Proxy 与 SUSPECT,不无限排队 | diff --git a/docs/development/implementation-plan.md b/docs/development/implementation-plan.md index d06c108..40ab467 100644 --- a/docs/development/implementation-plan.md +++ b/docs/development/implementation-plan.md @@ -195,11 +195,14 @@ Admin/Distribution 必需依赖。共享 `platform/httpserver` 与 已完成。pgx Adapter 已在真实 PostgreSQL 18 上运行同一公用契约,并验证 Repeatable Read 快照、`SKIP LOCKED`、原子 ACK、审计/Outbox 故障回滚和数据边界。 Admin `ApplicationService` 已将 mutation、权威管理快照、低基数运行态 -聚合与配置重载接到同一公用 seam;严格文件加载、脱敏管理摘要及原子配置发布 -已通过失败路径和并发测试。`cmd/proxy-controller` 与公用 `controller/bootstrap` +聚合与配置重载接到同一公用 seam;严格文件加载、外部密钥 HMAC 管理指纹及 +revision 单调配置发布已通过失败路径和确定性并发测试。`cmd/proxy-controller` 与公用 `controller/bootstrap` 已完成配置单次加载、PostgreSQL 连接/迁移、Redis 活动池、状态聚合、 -Distribution/Admin 服务构造、错误合并和资源关闭;Provider 调度及完整 HTTP -进程端到端测试仍待实现。Controller Metrics 独立入口现已提供 `/livez`、 +Distribution/Admin 服务构造、错误合并和资源关闭。生产 Provider Supervisor 已按 +权威管理状态动态装配 Upstream,并与 HTTP Runtime 通过公用 lifecycle Group 联动 +停机;Admin disable 会取消 Runtime,reload 在提交前预检并在发布后替换运行实例。 +组合 fixture 已验证隔离 Redis namespace 下的选主、Provider HTTP 调用、模板解析 +和活动池写入。Controller Metrics 独立入口现已提供 `/livez`、 `/readyz` 与基础 Prometheus 运行时指标,三监听器隔离已通过测试;业务指标仍待 实现。双存储 bootstrap 已通过 PostgreSQL 18 + Redis 8.2 组合 fixture,覆盖 迁移、启动配置提交、Readiness、Admin Status 和 Metrics 探针。 @@ -225,9 +228,17 @@ Managed。Gateway 已增加打包原子 Active/Reserved 读取与完整稀疏运 单调 report sequence 和报告 TTL 原子隔离旧实例,并由 `pool.InventoryReader` 汇总 权威 Managed/Available Slots;真实 Redis 8.2 已覆盖空报告、幂等重放、倒序、 冲突、超前 epoch、过期、单 Upstream 扫描隔离和预算耗尽的 fail-closed 行为。 -WorkerControlPlane gRPC 接收端、 -session 签发/心跳、Snapshot ACK 账本、Provider Fleet/bootstrap、全局 -`fetch.maxTotal` 和健康执行链仍待完成,因此本轮不勾选 Task 10 的组合验收项。 +Redis Provider Permit 现已把 requestInterval、maxInFlight 与 maxTotal 放在同一 +原子边界,按 expected 预留、实际合法数量结算,并支持失败保守计费、换主后结算和 +过期回收。响应型代理凭据使用独立、有界 lease,在 Redis Upsert、候选截断或解析 +失败后按版本释放;Provider Empty/Error 低基数计数已接入 Admin Status,配置删除 +时回收历史统计容量。Redis inventory 扫描上限固定覆盖配置允许的最大池,支持小池 +启动后动态扩容。Supervisor 以 PostgreSQL 权威 HMAC 指纹和 revision 栅栏协调 +多副本 reload:管理库瞬断沿用 last-known 状态,本地共享源落后时停止旧 Provider, +源匹配并预检后自动替换,迟到旧 revision 不覆盖新配置。 +WorkerControlPlane gRPC 接收端、session 签发/心跳、Snapshot ACK +账本、Client 分布式限流和健康执行链仍待完成,因此本轮不勾选 Task 10 的组合 +验收项。 ## Task 11: Checker and Health Reducer diff --git a/docs/operations/production-readiness.md b/docs/operations/production-readiness.md index 699060c..4718d0d 100644 --- a/docs/operations/production-readiness.md +++ b/docs/operations/production-readiness.md @@ -6,7 +6,7 @@ - [ ] 每个 Proxy 同一时刻最多归属一个 Worker,ownership epoch 单调。 - [ ] Reserved -> Active 使用单个原子转换,无超卖与负计数。 - [ ] Sequential 并发 Empty 只切换一次,旧 Upstream Proxy 自然耗尽。 -- [ ] `pool.maxSize` 与 `fetch.maxTotal` 分别按当前库存和累计获取计数。 +- [x] `pool.maxSize` 与 `fetch.maxTotal` 分别按当前库存和累计获取计数。 - [ ] Extract 只有 `AVAILABLE -> EXTRACTED`,OpenAPI 不存在 release/renew。 - [ ] Extract 状态更新和短期幂等结果位于同一个 Redis 原子操作。 - [ ] PostgreSQL 中不存在 Proxy 明细或逐次提取记录。 @@ -20,6 +20,7 @@ - [ ] trusted proxy 只包含受控 LoadBalancer/Ingress 网段。 - [ ] 解析前后均拦截私网、回环、链路本地、元数据地址与 DNS Rebinding。 - [ ] Secret 由外部密钥系统注入,镜像、ConfigMap、日志没有明文。 +- [ ] 所有 Controller 使用同一枚至少 32 字节的独立配置 HMAC 密钥,并完成轮换演练。 - [ ] Pod 以非 root、只读根文件系统、无 Linux capabilities 运行。 - [ ] NetworkPolicy 默认拒绝,外部数据库/Redis/Provider 网段已收紧。 - [ ] Provider 模板有响应大小、执行时间、函数与外部访问限制。 diff --git a/docs/operations/runbook.md b/docs/operations/runbook.md index ca4a951..854c50c 100644 --- a/docs/operations/runbook.md +++ b/docs/operations/runbook.md @@ -19,9 +19,9 @@ ## 2. 本地拓扑模板 `cmd/proxy-controller` 已完成配置单次加载、PostgreSQL 迁移、Redis 活动池、 -Distribution/Admin/Metrics 独立监听和有界停机装配。Provider 自动补池、业务 -指标以及 Gateway/Checker/Loadgen 三个进程仍属于 `implementation-plan.md` -后续任务。 +Distribution/Admin/Metrics 独立监听和有界停机装配。Provider 自动补池、分布式 +配额、动态重载和 Admin 低基数统计已装配;完整 Gateway/Checker/Loadgen 与 Worker +控制面仍属于 `implementation-plan.md` 后续任务。 因此 Compose/Kubernetes 资产当前仍用于评审网络、资源、探针和依赖关系,不能 视为完整可运行拓扑。 @@ -40,6 +40,7 @@ Distribution/Admin/Metrics 独立监听和有界停机装配。Provider 自动 $env:PROXY_POOL_GATEWAY_PASSWORD = "LOCAL_GATEWAY_PASSWORD" $env:PROXY_POOL_EXTRACT_TOKEN = "LOCAL_EXTRACT_TOKEN" $env:PROXY_POOL_ADMIN_TOKEN = "LOCAL_ADMIN_TOKEN" +$env:PROXY_POOL_CONFIG_FINGERPRINT_KEY = "LOCAL_HIGH_ENTROPY_KEY_AT_LEAST_32_BYTES" $env:PROVIDER_A_TOKEN = "PROVIDER_A_TOKEN" $env:PROVIDER_B_TOKEN = "PROVIDER_B_TOKEN" ``` @@ -90,6 +91,8 @@ Fetch 应表现为 Error 与退避,不应增加 Empty 计数,也不影响已 1. 使用托管 PostgreSQL 和 Redis,分别配置 TLS、备份、监控和多可用区。 2. 复制 `secret.example.yaml` 到环境私密配置系统,由 External Secrets、SOPS 或密钥管理平台生成 `proxy-pool-secrets`,不要提交真实 Secret。 + `PROXY_POOL_CONFIG_FINGERPRINT_KEY` 必须使用至少 32 字节的高熵随机值,所有 + Controller 副本保持一致,且与配置中的业务 Secret 分离管理。 3. 在环境 Overlay 替换镜像、Provider 地址、允许网段、外部存储地址、资源量 和 LoadBalancer 注解。 4. 根据集群 CNI 能力收紧 NetworkPolicy 的外部网段。 @@ -221,11 +224,15 @@ Outbox 发布器必须以稳定 consumer ID 有界领取;发布成功后原子 1. Gateway 继续使用最后有效 Snapshot。 2. Redis 健康且运行配置有效时,Distribution 继续执行原子 Extract,Provider - 继续刷新 TTL 活动池。 + 按 last-known 管理状态继续刷新 TTL 活动池;状态读取失败不得触发全进程退出。 3. 拒绝配置版本、Upstream/Routing 管理状态和其他需要 Admin 审计/outbox 的写入; 不得把 Proxy 明细临时落入 PostgreSQL。 4. 恢复后核对迁移、管理事务回滚、Admin 审计与 outbox backlog;不存在 Proxy 明细或逐次提取记录恢复步骤。 +5. 若权威配置指纹已变化,确认每个 Controller 的共享配置源和 Secret 版本已同步; + 同时确认 `PROXY_POOL_CONFIG_FINGERPRINT_KEY` 一致。指纹不匹配的副本会停止旧 + Provider,匹配并预检成功后按 PostgreSQL revision 自动恢复;迟到旧 revision + 不会覆盖较新本地配置。 ### 7.3 Redis 不可用 diff --git a/docs/requirements/traceability.md b/docs/requirements/traceability.md index 32a16c1..2fb3b2d 100644 --- a/docs/requirements/traceability.md +++ b/docs/requirements/traceability.md @@ -10,7 +10,7 @@ | ARCH-001 | 数据面 Worker 与控制面 Controller 分离 | 1-70 | 包、协议和部署拓扑已分离;Controller 命令已实现,Gateway/Checker/Loadgen 构建产物待实现 | | ARCH-002 | 热路径只做认证、本地路由和网络转发 | 1-70, 380-430 | Snapshot/Dispatch 及依赖边界已验证;完整 Gateway 进程与代表性性能剖析待完成 | | ARCH-003 | Gateway、Distribution、Admin、Metrics 独立入口 | 8904-8958 | Controller 命令已装配 Distribution/Admin/Metrics 三个独立监听及联动停机;Gateway 生产入口待装配 | -| ARCH-004 | Controller 集中 Provider 获取与切换 | 1403-1580 | 单进程 Reconciler、合并通知和切换领域契约已完成;分布式 Leader 与运行装配待完成 | +| ARCH-004 | Controller 集中 Provider 获取与切换 | 1403-1580 | Redis Leader、动态 Provider Supervisor 与 Bootstrap 生产装配已完成;Admin disable/reload 驱动取消替换,多副本按权威 HMAC 指纹和 revision 栅栏收敛并拒绝旧配置换主;Routing 切换到 Drain 的编排待完成 | | ARCH-005 | 100k QPS 峰值使用多 Worker 集群 | 当前会话 | 未验证设计目标;待代表性集群负载报告 | ## Routing 与 Upstream @@ -32,11 +32,11 @@ | FETCH-001 | 每个 Provider 有独立 requestInterval、maxInFlight、timeout 和 retry | 968-2394 | `provider/reconciler_test.go` | | FETCH-002 | 大量缺池信号合并为 singleflight/容量 1 通知 | 2067-2136, 8808-8849 | `coalesce.Signal` 与 100 并发通知测试 | | FETCH-003 | 错误使用指数退避和抖动,429 尊重 Retry-After | 1601-1831, 8808-8856 | `provider/reconciler_test.go` 与 `providerapi/http_adapter_test.go` | -| FETCH-004 | Provider 获取由单逻辑 Leader 执行 | 1403-1580 | Redis Coordinator 已通过真实 Redis 双实例互斥、epoch 接管、全局间隔/在途 Permit 与 generation 重建测试;Provider Fleet/bootstrap 接线待完成 | +| FETCH-004 | Provider 获取由单逻辑 Leader 执行 | 1403-1580 | Redis Coordinator 已通过真实 Redis 双实例互斥、epoch 接管、全局间隔/在途 Permit 与 generation 重建测试;生产 Supervisor/bootstrap 已通过 Admin disable 和 Provider HTTP 到隔离 Redis 库存的组合 fixture | | FETCH-005 | Empty 与 Error 分开;只有合法候选为零时 Empty++ | 8442-8529 | `fetch_result_test.go` 分类矩阵 | | FETCH-006 | 重复候选不当作 Empty,记录独立指标 | 8442-8480 | DuplicateOnly 分类与 Provider 测试 | | FETCH-007 | 模板限制响应大小、执行时间、函数集和外部访问 | 8808-8856 | `providerapi/template_parser_test.go` 输入、输出、候选、超时、递归与函数白名单测试 | -| FETCH-008 | pool.maxSize 与 fetch.maxTotal 语义分离 | 9190-9280 | `FetchBudget` 并发预占/释放测试 | +| FETCH-008 | pool.maxSize 与 fetch.maxTotal 语义分离 | 9190-9280 | 本地 `FetchBudget` 仅约束当前库存;Redis Permit 原子维护累计与 pending 额度,并通过换主、取消、幂等和过期保守结算测试 | ## Proxy 生命周期与容量 diff --git a/docs/testing/strategy.md b/docs/testing/strategy.md index e15c500..75d730d 100644 --- a/docs/testing/strategy.md +++ b/docs/testing/strategy.md @@ -22,11 +22,20 @@ 4. 连续 4 次 Empty 后 Valid 不切换;连续 5 次只从 A 切到 B。 5. Error 和 DuplicateOnly 不累计 Empty。 6. 100 个缺池信号只形成一个合并 Provider reconcile。 -7. 并发 Fetch 不突破 `pool.maxSize` 与 `fetch.maxTotal`。 +7. 并发 Fetch 不突破 `pool.maxSize`,且不会在 Redis `fetch.maxTotal` 停止阈值耗尽后发起新调用。 8. TTL safety margin 内不再分配。 9. Snapshot 版本断档、目标错误或校验和错误不替换当前视图。 10. 非幂等 HTTP 和已建立 CONNECT 不自动重放。 -11. 所有 Upstream 不可用时严格执行显式策略。 +11. Admin disable 取消目标 Provider Runtime;reload 构造失败不提交,成功时替换运行实例。 +12. 短 TTL 响应凭据使用独立 lease;并发 Fetch、截断、解析失败和 Redis Upsert + 后均准确释放且不互相撤销。 +13. PostgreSQL 状态瞬断保留 last-known Provider;多副本本地指纹落后时停止旧 + Runtime,共享源同步后自动预检并恢复;不同 HMAC 密钥不能误判为相同配置。 +14. 并发配置提交与 Supervisor 同步按 revision 单调发布,迟到旧 revision 不覆盖 + 已发布新配置。 +15. 配置删除的 Provider 统计项被回收,禁用但仍配置的统计项保留,容量可复用。 +16. 小池启动后重载到大池时,Redis inventory 扫描上限仍覆盖配置允许的最大池。 +17. 所有 Upstream 不可用时严格执行显式策略。 ## 3. 基础质量门禁 diff --git a/docs/testing/test-strategy.md b/docs/testing/test-strategy.md index 62ce053..16a6d39 100644 --- a/docs/testing/test-strategy.md +++ b/docs/testing/test-strategy.md @@ -120,7 +120,7 @@ Redis Readiness 和 Admin Status;HTTP Runner 使用测试 Adapter,避免占 Admin 应用层测试覆盖 typed-nil 依赖、Actor/SourceIP 映射、Routing CAS 错误、 权威管理快照与低基数运行态聚合、未知字段拒绝、主配置/Secret 文件 I/O 分类、 -持久化失败不发布、幂等重放发布、脱敏管理摘要和原子配置 Store 并发读写。静态 +持久化失败不发布、HMAC 管理指纹、revision 单调发布和原子配置 Store 并发读写。静态 导入边界测试禁止 Admin 引用 Redis Activity/Extract 与 Proxy 明细包。 需要 PostgreSQL/Redis 的测试使用独立实例和短生命周期容器,不复用开发数据。