proxy-pool/docs/testing/strategy.md

6.0 KiB
Raw Blame History

测试策略

本文保留为早期领域与容量检查清单。存储边界和当前执行命令以 test-strategy.md、ADR-005 为准Proxy 明细与逐次提取记录不写 PostgreSQL 独占提取只在 Redis TTL 活动池保留短期幂等结果。

1. 分层

  • 领域单测状态机、TTL、路由、容量、Fetch 分类和 Extraction 原子性。
  • 契约测试配置、OpenAPI、Protobuf 和 Provider Adapter fixture。
  • 文档契约:相对链接必须可解析,公开 Go 命令必须指向仓库内现有目标。
  • 集成测试Redis 活动池原子契约、PostgreSQL 管理事务、Leader/限流、 Outbox 与重建。
  • 端到端测试HTTP、CONNECT、Admin、Distribution 和优雅停机。
  • 负载测试Worker 调度微基准、50k 隧道 soak、集群 100k QPS 场景。

2. 必测不变量

  1. 1,000 个并发预留不突破单 Proxy 最大并发。
  2. 同一 Proxy 在并发 Extraction 中最多出现一次。
  3. allOrNothing 不足时不消耗任何候选。
  4. 连续 4 次 Empty 后 Valid 不切换;连续 5 次只从 A 切到 B。
  5. Error 和 DuplicateOnly 不累计 Empty。
  6. 100 个缺池信号只形成一个合并 Provider reconcile。
  7. 并发 Fetch 不突破 pool.maxSize,且不会在 Redis fetch.maxTotal 停止阈值耗尽后发起新调用。
  8. TTL safety margin 内不再分配。
  9. Snapshot 版本断档、目标错误或校验和错误不替换当前视图。
  10. 非幂等 HTTP 和已建立 CONNECT 不自动重放。
  11. Admin disable 取消目标 Provider Runtimereload 构造失败不提交,成功时替换运行实例。
  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. 基础质量门禁

gofmt -l .
go vet ./...
go test ./...
go test -race ./internal/...
go build ./...

go test ./docs 自动扫描 README、设计/部署文档和公开执行指南,拒绝失效的 相对链接以及指向尚不存在 Go 入口的运行命令。

真实 Redis 8.2 活动池契约使用独立 Compose fixture

.\scripts\test-redis.ps1

该 fixture 使用唯一命名空间,不执行 FLUSHDB,并关闭 AOF、RDB 与数据卷; 测试结束后按命名空间清理活动池、所有权和幂等键。

Controller 的 PostgreSQL + Redis 启动组合测试使用:

.\scripts\test-controller.ps1

单条测试命令超时 60 秒。依赖真实等待的用例必须改为 fake clock集成和 soak 测试单独标记,不混入快速单测。

4. 100k QPS 验收

测试报告必须记录:

  • CPU、内存、内核、网卡、文件描述符和 conntrack 配置。
  • Worker 数量、故障域、目标利用率和负载均衡算法。
  • HTTP/CONNECT 比例、keep-alive、请求/响应大小、上游 RTT 与失败率。
  • Proxy 总数、每 Proxy 容量、Routing 数和 Snapshot 更新频率。
  • 持续时间、P50/P95/P99、成功率、重试率、GC、RSS 和 goroutine 数。

只有在代表性环境持续达到目标且满足错误率和延迟门槛后,才能把“设计目标” 改为“已验证容量”。

5. 当前本地微基准

2026-08-07Windows/amd64、Go 1.26.4、Intel Core Ultra 7 155H以固定 -count=1 -benchtime=1x 运行:

BenchmarkAcquire100kIndexed-22               1       13100 ns/op      256 B/op       2 allocs/op
BenchmarkAcquire100kRoutingRoundRobin-22      1       45200 ns/op    13680 B/op      81 allocs/op
BenchmarkStoreApply100k-22                    1   539017100 ns/op 684677920 B/op 3001735 allocs/op

使用 ./scripts/benchmark-gateway.ps1 可复现该固定单次基线,输出写入被 Git 忽略的 dist/gateway-benchmarks.txt 并附带 revision。单次基准存在运行噪声应只用于发现明显回归 性能比较需要在同规格环境增加多次迭代后另行保存原始证据。

Acquire 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。 Store.Apply 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配, 暂不自动回收曾出现过的 Proxy ID但注册表有 1,000,000 项硬上限,达到上限时 拒绝新 Snapshot 并保留旧视图。后续需要基于 RCU/引用计数定义安全回收点。 这些数据不包含网络、认证、Provider、存储或多 Worker 协调,不能作为 100k QPS 端到端验收结论。

6. Gateway 本地故障证据

Gateway 快速测试使用本地假上游,不依赖公网:

  • HTTP 正向代理成功、拨号失败后 GET 排除旧 Proxy 重试、407 原样返回。
  • POST 默认单次尝试CONNECT 只在 Client 200 前允许配置式重试。
  • CONNECT 保留握手后缓冲字节和 TCP 双向 half-close。
  • Dial、握手、响应头、错误正文、隧道 buffer 与 idle timeout 均有边界。
  • Handler.Shutdown 等待在途 HTTP/CONNECT截止时间到期后关闭 Hijacked 隧道、释放 Active 容量,并拒绝新请求。
  • literal IP 与所有 DNS A/AAAA 结果先校验,再把已验证 IP 绑定到传输目标。
  • CONNECT 默认端口白名单、保留/CGNAT/元数据地址和显式端口覆盖均有测试。
  • Provider 响应凭据经不透明引用写入公共存储,再由 Gateway Resolver 恢复; 跨包链路和明文泄漏均有回归测试。

这些用例证明协议与故障语义,不替代多 Worker、真实带宽和长时间 soak 的 100k QPS 验收。