# 测试与容量验证策略 ## 1. 原则 - 先证明领域不变量,再证明 Adapter 契约,最后证明跨进程行为。 - 并发测试必须在 race detector 下运行,不能只依赖单线程示例。 - 时间、随机、网络、Provider 和存储均通过可替换接口或 fixture 控制。 - 生产 Adapter 必须证明数据边界:Proxy 明细只进入 Redis TTL 活动池和节点 内存,PostgreSQL 不得出现 Proxy 明细或逐次提取记录。 - 100,000 QPS 是待验证的集群目标,不以架构图、副本数或短时峰值替代证据。 - 性能通过与正确性通过相互独立;高 QPS 下出现超卖、重复 Extract 或状态 回退时,结果一律失败。 ## 2. 测试分层 ### 单元测试 - Proxy 唯一键、TTL 优先级、状态机和 safety margin。 - Atomic Capacity 的 Reserve、Commit、Cancel、Release 与幂等错误。 - Routing first-match 与五种策略。 - Fetch Success、Empty、Duplicate-only、Error 分类。 - Backoff、jitter、Retry-After、requestInterval、maxInFlight。 - Extraction eligibility、partial、allOrNothing、health age、TTL、reserve。 - 配置严格字段、交叉引用、正则、监听保护和独立计数语义。 ### 契约测试 - Provider 响应模板的大小、超时、函数白名单和解析边界。 - Redis Lua/Function 对候选筛选、库存预留、独占移除和短期幂等结果执行单次 原子操作;并发与主从切换下不得部分提交。 - PostgreSQL 配置版本、Upstream/Routing 管理状态、Admin 审计与 outbox 的事务 更新及幂等重放;测试库断言不包含 Proxy 明细或逐次提取记录。 - Redis TTL 活动池、Leader 租约、Provider 请求额度、Distribution Client 跨副本限流、短期幂等窗口和失联恢复。 - Snapshot/Delta/ACK/Report 的版本与校验和兼容性。 - OpenAPI 错误模型、认证矩阵、批量 fulfillment。 - OpenAPI 本地引用闭合、operationId 唯一、响应集合和 security scheme 引用。 - README、设计/部署文档中的相对链接,以及公开 Go 命令引用的仓库目标。 ### 集成与端到端 - HTTP 正向代理成功、上游连接前失败和安全重试。 - HTTPS CONNECT 建立后不透明重放。 - Controller Fetch -> Redis TTL 活动池 -> Check -> AVAILABLE -> Worker Snapshot -> Gateway 转发;Gateway 请求线程始终只读节点内存。 - Distribution 原子提取后 Gateway 不再分配同一 Proxy。 - 配置热更新失败保留旧 Revision,成功后新请求使用新 Snapshot。 ## 3. 必测的 12 类场景 1. **并发容量**:1000 协程争用同一 Proxy,始终满足 `active + reserved <= effectiveMaxConcurrency`。 2. **Reservation 生命周期**:Dial 成功/失败、超时、取消和重复 Release 均不 泄漏或产生负计数。领域层已覆盖 Cancel、重复终结、错误顺序和同一 Reservation 并发终结;Gateway Handler 覆盖建连失败、重试和请求取消。 3. **singleflight**:100 个缺池信号只产生一个有效 Fetch 调度。 4. **Provider 限流**:requestInterval、maxInFlight、timeout、重试和 429 `Retry-After` 在虚拟时钟下准确。 5. **Fetch 分类**:Error 不动 Empty;合法空响应 Empty++;duplicate-only 重置 Empty;Success 重置 Empty。 6. **Sequential 竞态**:达到阈值时多协程只能将 A 切到 B 一次,不能越过 B。 7. **Drain**:切换或禁用 Upstream 后停止新分配,已有连接完成后才回收。 8. **Extract 竞态**:多个请求并发提取同一候选集合,同一 Redis 活动池代次内 每个 Proxy 最多返回一次。 9. **Extract 批量语义**:partial 提交实际数量;allOrNothing 不足时 Redis 活动池和幂等结果均不变;始终保留 `reserveForGateway`。 10. **Worker ownership**:回收过程严格经过 DRAINING、ACK、active/reserved=0、 unowned,旧 Snapshot 不可再分配。 11. **控制面故障**:Redis、PostgreSQL、Controller、Checker 与 Provider 分别 失效时,行为与 Runbook 一致,Gateway 热路径不被同步依赖拖垮。 12. **Outcome 栅栏**:队列写入不阻塞转发;同一 session 的相同序列/摘要可重放, 相同序列的不同摘要冲突,较小序列拒绝;Session 替换后旧 Worker 结果拒绝。 ## 4. 测试命令 所有后台测试都设置 60 秒上限: ```powershell go test -timeout 60s ./... go test -timeout 60s -race ./internal/... go vet ./... go build ./... ``` `go test ./docs` 是文档契约门禁:递归校验相对链接,并确认用户指南中的 `go run`/`go build` 具体目标真实存在;通配包命令继续由 Go 工具链验证。 Redis 活动池 Adapter 与内存参考实现共享同一套公用行为契约。真实 Redis 8.2 fixture 的执行命令是: ```powershell .\scripts\test-redis.ps1 ``` 契约覆盖 Upsert/去重/容量、健康更新、partial/allOrNothing 提取、Gateway 保留、 零数量与非零数量幂等、幂等硬过期、Worker 所有权/Drain/ACK、库存、过期清理、 100 轮并发提取和 100 轮所有权竞争。fixture 使用唯一命名空间,不执行 `FLUSHDB`;本地 Redis 关闭 AOF、RDB 和数据卷,避免短效 Proxy 与凭据落盘。 PostgreSQL 管理面使用 `adminstate/contracttest` 作为 Memory/PostgreSQL 公用 行为契约,执行命令是: ```powershell .\scripts\test-postgres.ps1 ``` pgx Adapter 已在真实 PostgreSQL 18 上覆盖配置事务、Upstream 幂等、100 并发 Routing CAS、Repeatable Read 快照、审计分页、Routing no-op、`SKIP LOCKED` 租约、原子批量 ACK,以及审计/Outbox 写入失败时的完整回滚。fixture 为每个测试 创建唯一 Schema,只删除该 Schema;数据库使用回环端口和 tmpfs,测试后不保留 数据卷。静态与 `information_schema` 双重检查证明只存在六张管理表,且没有 Proxy、凭据、逐次提取、Worker ownership 或幂等明细列。 Controller bootstrap 的双存储组合验证命令是: ```powershell .\scripts\test-controller.ps1 ``` 该 fixture 同时启动 PostgreSQL 18 与 Redis 8.2,验证迁移、启动配置提交、 Redis Readiness 和 Admin Status;HTTP Runner 使用测试 Adapter,避免占用业务 监听端口。测试数据仅存在于隔离 Compose 项目和 PostgreSQL tmpfs。 Admin 应用层测试覆盖 typed-nil 依赖、Actor/SourceIP 映射、Routing CAS 错误、 权威管理快照与低基数运行态聚合、未知字段拒绝、主配置/Secret 文件 I/O 分类、 持久化失败不发布、HMAC 管理指纹、revision 单调发布和原子配置 Store 并发读写。静态 导入边界测试禁止 Admin 引用 Redis Activity/Extract 与 Proxy 明细包。 需要 PostgreSQL/Redis 的测试使用独立实例和短生命周期容器,不复用开发数据。 测试结束后验证没有残留 Worker ownership、Leader 租约、活动池条目或幂等键, 并检查 PostgreSQL 中不存在 Proxy 明细和逐次提取记录。 ## 5. 负载模型 必须分开运行,避免不同瓶颈互相掩盖: ### HTTP QPS - GET/HEAD 占比、响应体大小、Keep-Alive 复用率与生产预测一致。 - 依次运行 10k 稳态、阶梯升压和 100k 峰值。 - 同时记录端到端与 Gateway 内部 Dispatch 延迟。 ### CONNECT - 分开测试活跃隧道数和每秒新建隧道数。 - 包含短连接、长连接、半关闭、Client 取消和上游主动断开。 - 验证 200 已发送后不发生透明重放。 ### Snapshot - 1k、10k、100k Proxy Snapshot,测构建、校验、原子切换、内存峰值和 GC。 - 在满负载下发布 Snapshot,确认请求线程不参与索引构建。 ### Extract - 小批 partial、大批 allOrNothing、高冲突 filter 和库存不足。 - 与 Gateway 同时运行,持续检查 `reserveForGateway` 和无重复返回。 ### 故障负载 - 负载运行中断开 Controller、Redis、PostgreSQL、一个 Worker 和一个可用区。 - Provider 注入 DNS、超时、500、429、超大响应、模板错误和合法空响应。 - Checker 注入慢目标与队列积压。 ## 6. 通过条件 业务 SLO 由产品最终确认,但至少满足以下工程门槛: - 无容量超卖、负计数、幂等窗口内重复 Extract、Admin 审计缺失或状态非法回退。 - 100k 峰值期间无进程 OOM、FD 耗尽、无界队列或全局锁热点。 - Gateway 热路径在 PostgreSQL、Redis、Provider 失效时不发起同步访问。 - p99 Dispatch 小于 100 微秒的设计预算需要在 100k Proxy Snapshot 下单独证明。 - 最大故障域丢失后,剩余容量仍满足约定 SLO;否则增加副本或降低承诺容量。 - Snapshot 超过 `maxStaleAge` 后 Gateway 拒绝新流量,已有连接按时排空。 - 所有数据、命令、Git SHA、镜像 digest、环境和原始指标可以复现。 ## 7. 测试报告模板 ```text 版本:Git SHA / image digest / Go version 环境:节点、CPU、内存、NIC、内核、Kubernetes/CNI 配置:Snapshot 规模、Proxy 容量、路由、重试、日志级别 场景:协议、连接复用、响应体、持续时间、升压曲线、故障注入 结果:QPS、建连速率、active、p50/p95/p99、错误、CPU、RSS、GC、FD、网络 不变量:capacity、ownership、extraction、idempotency、admin audit、reserve 检查结果 结论:通过/失败,以及适用边界 ```