proxy-pool/docs/testing/test-strategy.md
youfak c3b5b25597
Some checks are pending
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
ci / race (push) Waiting to run
ci / integration (push) Waiting to run
docs: record distributed admission delivery
2026-07-30 21:04:19 +08:00

186 lines
9.0 KiB
Markdown
Raw 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.

# 测试与容量验证策略
## 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. 必测的 11 类场景
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
重置 EmptySuccess 重置 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 热路径不被同步依赖拖垮。
## 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 StatusHTTP 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 检查结果
结论:通过/失败,以及适用边界
```