107 lines
4.6 KiB
Markdown
107 lines
4.6 KiB
Markdown
# 测试策略
|
||
|
||
> 本文保留为早期领域与容量检查清单。存储边界和当前执行命令以
|
||
> `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` 与 `fetch.maxTotal`。
|
||
8. TTL safety margin 内不再分配。
|
||
9. Snapshot 版本断档、目标错误或校验和错误不替换当前视图。
|
||
10. 非幂等 HTTP 和已建立 CONNECT 不自动重放。
|
||
11. 所有 Upstream 不可用时严格执行显式策略。
|
||
|
||
## 3. 基础质量门禁
|
||
|
||
```powershell
|
||
gofmt -l .
|
||
go vet ./...
|
||
go test ./...
|
||
go test -race ./internal/...
|
||
go build ./...
|
||
```
|
||
|
||
`go test ./docs` 自动扫描 README、设计/部署文档和公开执行指南,拒绝失效的
|
||
相对链接以及指向尚不存在 Go 入口的运行命令。
|
||
|
||
真实 Redis 8.2 活动池契约使用独立 Compose fixture:
|
||
|
||
```powershell
|
||
.\scripts\test-redis.ps1
|
||
```
|
||
|
||
该 fixture 使用唯一命名空间,不执行 `FLUSHDB`,并关闭 AOF、RDB 与数据卷;
|
||
测试结束后按命名空间清理活动池、所有权和幂等键。
|
||
|
||
Controller 的 PostgreSQL + Redis 启动组合测试使用:
|
||
|
||
```powershell
|
||
.\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-07-28,Windows/amd64、Intel Core Ultra 7 155H:
|
||
|
||
```text
|
||
BenchmarkAcquire100kIndexed-22 3553592 640.0 ns/op 256 B/op 2 allocs/op
|
||
BenchmarkStoreApply100k-22 1 472.7 ms/op 654 MB/op 2700642 allocs/op
|
||
```
|
||
|
||
`Acquire` 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。
|
||
`Store.Apply` 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配,
|
||
暂不自动回收曾出现过的 Proxy ID。后续需要基于 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 验收。
|