proxy-pool/findings.md
2026-07-29 21:30:09 +08:00

176 lines
10 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.

# 对话内容提取结果
## 权威来源
- 文件:`对话内容.md`
- 大小167,284 字节
- 行数9,404 行
- 读取时间2026-07-28
## 最终产品边界
系统同时提供两种入口:
1. Gateway系统选择上游代理并代转发 HTTP、HTTPS CONNECT预留
SOCKS5 扩展。
2. Distribution API一次性、独占地返回真实上游代理。代理成功提取后
立即从可分配池移除,不需要租约、释放接口或使用量追踪。
系统管理多个 Upstream Provider并使用配置化 Routing 决定 Gateway 或
Extract 请求使用哪些 Upstream。
## 后出现并覆盖早期建议的决策
- Distribution API 的 Lease/Release/Shared Allocation 方案被最终的
Exclusive Extraction 取代。
- `pool.maxSize` 表示当前系统维护的未提取代理硬上限;累计供应商提取额度
使用独立的 `fetch.maxTotal`,不能复用同一个字段。
- `switchAfterEmptyFetch` 只统计“上游请求成功、解析成功,但解析后没有任何
合法代理”的结果超时、HTTP 错误、认证错误、DNS 错误和模板错误只计
`fetchErrorCount`。全重复结果不当作空结果,单独记录。
- `consecutiveEmptyFetch` 属于 UpstreamSequential 当前选择属于 Routing。
某 Upstream 达到阈值时,引用它的 Routing 原子切换;已有代理继续耗尽。
- Extract API 默认部分满足 `partial`;也支持 `allOrNothing`
- Extract API 从 `AVAILABLE` 原子转换到 `EXTRACTED` 后才返回,保证同一代理
永不发放两次。
## 核心不变量
- 请求热路径不得调用 Provider API也不得查询全量 Redis/PostgreSQL 后排序。
- 代理分配必须原子预留容量,防止并发超卖。
- 代理唯一键为 `scheme + host + port + username + credentialVersion`;日志
和指标不得暴露密码。
- TTL 优先级为响应 `expiresAt`、响应 `ttl`、配置固定 TTL活动池中的每个
Proxy 必须有明确过期时间,内部时间统一 UTC。
- 健康检查至少区分全局健康和 Routing/目标健康,并使用抖动和并发上限。
- GET/HEAD 可按配置安全重试非幂等方法默认不自动重试CONNECT 建立后
不透明重放。
- 默认不直连;所有 Upstream 不可用时必须显式选择 reject、wait 或 direct。
- Gateway、Distribution、Admin、Metrics 使用独立监听和认证/访问控制。
- 非回环监听且无认证、无 CIDR 保护时,严格模式必须拒绝启动。
## 集群与性能
- 用户补充:高峰可能达到 100,000 请求/秒。
- 数据面采用多 Worker本地不可变代理快照和本地容量计数。
- 同一代理必须由单个 Worker 所有,或由控制面下发容量切片;禁止每请求
访问 Redis 做全局并发计数。
- 控制面集中 Provider 获取、独立限流、singleflight、Leader 选举和快照分发。
Proxy 明细只进入 Redis TTL 活动池,不写 PostgreSQL。
- 副本数必须由单 Worker 实测能力、目标利用率和故障域余量计算。
## 配置模型
顶层包含:`version`、`defaults`、`security`、`gateway`、`distribution`、
`admin`、`metrics`、`storage`、`routing`、`upstreams`。
每个 Upstream 包含:`enabled`、`exposure`、`provider`、`api`、`proxyAuth`、
`pool`、`capacity`、`lifecycle`、`fetch`、`check`。
Routing 自上而下匹配,首条命中停止;支持 Gateway 与 Extract 两种 purpose
策略至少包括 sequential、random、roundRobin、weighted、leastConnections。
## 必测场景
- 连续 4 次空后成功不得切换;连续 5 次空只切换一次。
- 100 个并发缺池请求只触发有限次 Provider fetch。
- 并发切换不能从 A 一次跳到 C。
- 并发 fetch 不得突破 pool.maxSize 或 fetch.maxTotal。
- TTL safety margin 内不得分配。
- Gateway 与 Extract 共享池时不得容量超卖或重复提取。
- 配置原子热更新期间请求不中断。
- Provider 超时不得计入 Empty Fetch。
- 重复代理不得重复入池,也不得触发空结果切换。
- 所有 Upstream 不可用时按显式策略执行。
## Checker 与健康归并事实2026-07-29
- Checker 是可水平扩展的事实采集进程,只执行有截止时间的探测并上报
Observation只有 Controller Reducer 能改变权威 Proxy/目标健康状态。
- 健康层级为 BASIC、EGRESS、TARGET。新 Proxy 必须先完成全局基础检查;目标级
失败只影响对应 Routing/Target Profile不得把全局仍健康的 Proxy 淘汰。
- 全局状态规则固定为:首次有意义失败进入 SUSPECT连续失败达到
`maxConsecutiveFailures` 后进入 UNHEALTHY复检成功恢复 AVAILABLE。
- 调度不能为每个 Proxy 建立常驻 goroutine 或无界队列;必须稳定分散任务、加入
jitter、限制 `maxInFlight`,并按 FETCHED、SUSPECT、AVAILABLE 的顺序优先。
- 现有 `activitypool.HealthStore.ApplyHealth` 只能提交最终状态、时间和延迟,不能
原子维护连续失败计数或目标级 Profile新模块需要将“纯 Reducer 决策”和
“活动池原子提交”分离,通过公用窄接口复用 Memory/Redis 行为契约。
- `api/proto/controlplane/v1/controlplane.proto` 已定义 CheckTask、CheckLevel 和
HealthObservation后续 Go 领域类型必须保持字段语义一致,但不直接依赖生成的
transport 类型。
## Git 同步事实2026-07-29
- PostgreSQL 管理面基础文档已提交为 `7951c29`
- 推送远端时返回 `Authentication failed`;没有重复相同失败操作,本地提交保持
完整,待 Git 凭据恢复后同步。
## Routing/Sequential 验收审计2026-07-29
- 五种 Routing 策略已有独立领域实现和单测,但 `Rule` 未携带 Strategy/
OnUnavailableGateway 仍把全部 Upstream 交给一个全局轮询 Dispatcher配置
策略尚未影响真实请求链。
- `onUnavailable` 已严格校验 reject/wait/direct但 Gateway 无候选时统一返回
503wait/direct 和默认 reject 尚未形成运行时闭环。
- Sequential 当前版本 CAS 只在单进程内生效,构造时总从第一个 Upstream 开始;
PostgreSQL 管理态尚未接入游标恢复和跨实例 CAS。
- 单 Upstream Sequential、默认 endBehavior、disabled candidate 的最终语义与
现有代码/需求存在差异,进入设计确认项,不在测试中固化未确认行为。
## Proxy Capacity 验收审计2026-07-29
- 每个 Proxy ID 已有独立打包原子计数,固定 Max 下 1,000 并发不会超卖;这满足
当前 Gateway 热路径的基本预留不变量。
- Reservation 已补齐 Cancel、重复终结、错误顺序和并发 Commit/Cancel/Release
的领域测试Gateway 仍会忽略 Release/Cancel 错误,尚无低基数不变量观测 seam。
- `SetMax` 与 counters 分离更新;降到当前占用以下时会出现 overcommitted 状态,
需要先确定“拒绝降容”或“允许排空”的正式契约。
- Snapshot Store 永久保留见过的 Proxy ID 对应 Capacity短 TTL、高换 IP 场景下
需要排空后回收,避免运行态注册表长期增长。
## Routing Runtime 设计输入2026-07-29
- `对话内容.md` 最后一个明确建议将 Sequential `endBehavior` 默认设为 `stop`
当前领域构造器默认 `stayLast`,配置参考只展示显式值,三者需要统一。
- 产品安全默认已确定为 `onUnavailable=reject`,但当前严格配置要求字段必填;
需要确认省略时自动补 reject还是继续拒绝启动。
- disabled Upstream 的确定语义是停止 Fetch、健康检查和新分配已有 Proxy/连接
自然排空Sequential 是临时跳过还是永久推进尚需固化。
- `direct` 对 Gateway 表示经过目标安全策略后绕过代理直连;对独占提取没有可返回
的 Proxy推荐在 `purpose=extract` 时拒绝 `direct` 配置。
- 推荐采用混合 Routing RuntimeController 维护 Sequential 权威游标和跨实例
CASGateway 消费不可变路由快照并在本地执行 random/roundRobin/weighted/
leastConnections热路径不访问 Redis/PostgreSQLDistribution 在 Controller
内复用同一编译策略并交给 Redis 原子提取执行。
- Gateway 当前没有完整进程装配,`RulesRouter` 仅存在于领域/Handler 测试;
Distribution 只接受调用方 `allowedUpstreams`,尚未把 `purpose=extract` 路由与
Client 许可集求交。
## 架构证据一致性审计2026-07-29
- `.github/workflows/ci.yml` 已覆盖 Windows/Linux vet、unit、build 及 Linux race
`scripts/verify.ps1` 也覆盖格式、vet、60 秒单测、条件 race 和 build因此两项
基础工程验收应计为完成。
- OpenAPI 通过 Go 测试执行结构/路径/响应码检查Protobuf descriptor 曾手工编译
通过,但 CI 没有安装/调用 `protoc`;“在 CI 编译 descriptor”仍未完成。
- `cmd/proxy-gateway`、`proxy-controller`、`proxy-checker`、`proxy-loadgen` 均不存在;
Docker/Kubernetes 当前只是目标拓扑,不能作为构建产物或运行验证证据。
- Provider Reconciler 的合并通知和请求约束已完成,但没有 Redis Leader Adapter
或多实例锁测试FETCH-004 仍是未完成要求。
- Checker/Health 当前只有配置、Protobuf 和 Proxy 状态迁移骨架,没有 Scheduler、
Reducer 或目标 ProfileHEALTH-001..003 不能记为已实现。
- 当前没有 Prometheus 指标模块或描述符测试OBS-001 只有文档约束,运行时证据
缺失。
- Available Slots 当前纳入 AVAILABLE、TTL、安全余量、Max、Active、Reserved
ownership、route/target health 与 Gateway reserve 尚未进入同一聚合模型。
## 文档可执行性审计2026-07-29
- 文档相对链接人工扫描通过,但原先缺少持续门禁;新增 `docs` 包契约测试,统一
扫描 README、docs、deploy 与 diagrams防止链接随文件调整后失效。
- 配置参考曾把尚不存在的 `cmd/proxy-controller` 作为推荐启动命令;现改为真实
可执行的 `deploy/tools/configcheck`,并明确生产 Controller 入口仍是计划能力。
- 文档中的具体 `go run`/`go build` 目标现在必须存在;包含 `...` 的通配包命令
由 Go 工具链自身解析并在完整验证中执行。