Go to file
2026-08-07 16:16:00 +08:00
.github/workflows build: generate worker control plane grpc contract 2026-07-31 10:44:32 +08:00
api feat: support static gateway direct routes 2026-08-07 16:16:00 +08:00
cmd feat: persist loadgen reports 2026-08-07 15:46:10 +08:00
configs feat: add worker control plane configuration 2026-07-31 10:49:08 +08:00
deploy fix: account for queued loadgen rate starts 2026-08-07 16:00:09 +08:00
diagrams feat: add ephemeral proxy activity pool 2026-07-29 12:51:18 +08:00
docs feat: support static gateway direct routes 2026-08-07 16:16:00 +08:00
examples/config feat: add Redis provider coordination 2026-07-30 14:15:48 +08:00
gen/controlplane/v1 feat: support static gateway direct routes 2026-08-07 16:16:00 +08:00
internal feat: support static gateway direct routes 2026-08-07 16:16:00 +08:00
scripts build: generate worker control plane grpc contract 2026-07-31 10:44:32 +08:00
.gitignore feat: add controller startup bootstrap 2026-07-30 11:38:33 +08:00
CONTEXT.md feat: add ephemeral proxy activity pool 2026-07-29 12:51:18 +08:00
findings.md feat: add secret-safe process logging 2026-08-02 14:29:10 +08:00
go.mod build: generate worker control plane grpc contract 2026-07-31 10:44:32 +08:00
go.sum build: generate worker control plane grpc contract 2026-07-31 10:44:32 +08:00
progress.md feat: add secret-safe process logging 2026-08-02 14:29:10 +08:00
README.md fix: account for queued loadgen rate starts 2026-08-07 16:00:09 +08:00
task_plan.md feat: observe gateway capacity invariants 2026-08-02 14:45:47 +08:00
对话内容.md docs: define proxy pool architecture from full conversation 2026-07-28 18:08:59 +08:00

Proxy Pool

项目定位

面向多供应商动态代理资源的集中控制、独占提取与高并发转发平台。

Proxy Pool 将供应商接入、短 TTL 代理活动池和管理状态集中到 Controller 同时提供三类边界清晰的访问方式。集群 100,000 QPS 是设计目标,尚未经过 代表性环境的负载测试证明。

项目背景

不同代理供应商的响应格式、鉴权方式、计费方式和代理存活时间并不一致;部分 代理只有几十秒有效期。系统还需要同时处理容量预留、健康状态、路由切换、 一次性提取和高并发转发。

Proxy Pool 用 Controller 协调这些变化,并让 Gateway 数据面只消费节点内存中的 不可变快照,避免在转发热路径查询 PostgreSQL、Redis 或 Provider API。

使用方式

  • Gateway:调用方连接平台,由平台选择上游代理并转发 HTTP 或 HTTPS CONNECT。proxy-gateway 已装配本地监听、指标探针和控制面 Register/Watch/ACK/ Runtime/Outcome 会话;带凭据 Proxy 的分发与当前内存 View 已闭环。
  • Distribution:调用方按条件提取真实代理;成功提取即独占消费,不支持归还、 续租或状态查询。
  • Admin:运维人员查询状态、启停 Upstream、切换 Routing并触发严格配置 重载。Admin 与 Distribution 已由 Controller 运行在独立监听器上。

核心能力

  • 严格配置:配置版本 1、YAML 未知字段拒绝、Secret 引用解析、公开监听保护、 引用和容量边界校验。
  • Provider 获取与协调Provider HTTP Client、响应上限、模板解析、分布式 Leader/请求额度、退避和补池 Supervisor 已接入 Controller。
  • Redis 活动池:短 TTL Proxy Upsert、去重、健康更新、Worker ownership、 库存、过期清理、Distribution 幂等与分布式限流均使用原子操作或有界流程。
  • Distribution:支持 partial / allOrNothing、TTL 与健康过滤、Gateway 库存预留,以及 AVAILABLE -> EXTRACTED 的一次性独占提取。
  • Controller 入口proxy-controller 已装配 Distribution、Admin、Metrics、 PostgreSQL 迁移与 Redis 活动池,并支持联动优雅停机。
  • Checker 指标Metrics 启用时暴露 Checker 任务下发与 Observation 接受/拒绝计数; 标签仅使用固定检查级别和结果,不记录 Proxy、IP、URL 或凭据。
  • Gateway 指标Metrics 启用时暴露代理尝试的固定阶段成功/失败计数、本地 Outcome 队列满后的丢弃计数、HTTP/CONNECT 已接收请求数与在途数,以及活跃 CONNECT 隧道数;协议标签仅有 HTTP 与 CONNECT不记录 Proxy、路由、目标、 客户端或凭据。
  • Drain 指标Controller 暴露 proxy_pool_controller_drain_candidates_totalproxy_pool_controller_drains_started_totalreason 仅有 unhealthyupstream_disabled,不包含 Proxy、Worker、Upstream、会话或地址。
  • Provider 指标Controller 暴露 proxy_pool_controller_provider_fetch_results_total{class}proxy_pool_controller_provider_valid_candidates_totalproxy_pool_controller_provider_new_proxies_totalclass 仅有 validemptyduplicate_onlyerror,不包含 Upstream、Proxy 或错误文本标签。
  • 提取指标Controller 暴露 proxy_pool_controller_extraction_requests_total{result}proxy_pool_controller_extraction_requested_proxies_totalproxy_pool_controller_extraction_returned_proxies_totalresult 仅有完成、 部分、空、库存不足、幂等冲突、限流、不可用、无效与内部错误等固定枚举, 不包含 Client、请求、过滤条件、Upstream、Proxy 或错误文本标签。
  • 容量指标Controller 在既有 Provider 库存对账周期聚合托管 Proxy、可用/有效 Slot、待拉取数量和活跃上游数并暴露 proxy_pool_controller_capacity_inventory_reads_total{result}result 仅有 successerror,不按 Upstream、Worker、Proxy、会话或地址拆分。
  • PostgreSQL 管理面持久化配置版本、Upstream/Routing 管理状态、Admin 审计与 Outbox不保存 Proxy 明细或逐次提取记录。
  • Gateway 组件HTTP 正向代理、HTTPS CONNECT、双向 Tunnel、重试、超时、 目的地址保护、本地快照存储、容量调度和 Worker 控制面 Register/Watch/ACK/ Runtime/Outcome 会话组件已有实现与定向测试。每次代理尝试只向本地有界队列写入 Outcome微批确认失败会重发同一序列队列满时丢弃观测样本不阻塞转发请求。 SessionSupervisor 会为可恢复控制面中断执行 有界退避重连。Controller 可向 Worker 下发已归属 Proxy、Gateway Routing 与按引用去重的 凭据材料快照。Gateway 会将 Routing、Proxy 与凭据原子编译为同一内存 View并只按当前未过期 View 匹配请求,并在内存中按 Sequential、Random、Round Robin、Weighted 或 Least Connections 选择上游。无候选时支持 reject、受 waitTimeout 限制的本地容量等待, 以及仍经过目标地址策略的 directproxy-gateway 通过独立控制面拨号地址维护 Session并在每份 Snapshot 有效期的一半前接收版本递增的完整刷新;仅在持有未过期 Snapshot 时 Ready凭据材料只保留在当前节点内存 View。Controller 内成功提交的 Upstream 启停、Routing 切换和配置发布会向本进程全部在线 Worker 快照流广播刷新; 定时刷新仍作为跨进程收敛与失效保护。
  • Gateway 粘性会话:可为已认证请求启用 X-Proxy-Session 等配置 Header Gateway 以 Client、Routing 和会话值派生本地有界绑定,成功建连后固定到同一 Proxy并在代理失效、快照移除或转发失败时自动重绑。原始会话值不会写入日志、 指标、PostgreSQL 或 Redis也不会向目标站点转发。
  • 安全边界Gateway、Distribution 与 Admin 使用各自的认证语义,并支持 CIDR、可信代理、严格请求解析和敏感信息最小化Admin 的读写权限与 Distribution 提取权限可按命中凭据分别收敛。Distribution 凭据还可限制单次 提取数量、可访问 Upstream 与地区Gateway 凭据可限制可访问 Routing未配置时 保持既有全范围行为。Gateway 凭据还可在每个 Worker 内限制每分钟请求数, 同时限制 HTTP 请求和 CONNECT 隧道的并发数;热路径计数不写入 Redis 或 PostgreSQL。

架构概览

flowchart LR
    Client[调用方] -->|HTTP / CONNECT| Gateway[proxy-gateway]
    Client -->|独占提取| Distribution[Distribution]
    Operator[运维人员] -->|管理操作| Admin[Admin]
    subgraph CP[proxy-controller 已运行]
        Distribution --> Controller[Controller]
        Admin --> Controller
    end
    Controller -->|Fetch| Provider[Provider API]
    Controller --> Redis[(Redis)]
    Controller --> PostgreSQL[(PostgreSQL)]
    Checker[Checker<br/>任务协议已接入] -. Observation .-> Controller
    Controller -. gRPC Snapshot .-> Gateway
  • PostgreSQL 只保存管理面状态,不保存 Proxy 明细或逐次提取记录。
  • Redis 保存短 TTL Proxy 活动池、Provider 协调、Distribution 幂等与分布式 限流等可重建的短期状态。
  • Gateway 热路径 只读取节点内存,不查询 PostgreSQL、Redis 或 Provider API。

当前完成度

截至 2026-08-02,实施计划中可直接勾选的检查项为 60 / 7481.1%。详情见 实施计划交付完成度审计

  • 已完成严格配置、Provider 获取与协调、Redis 活动池、Distribution 原子 提取与限流、Controller 的 Admin/Distribution/Metrics 监听,以及 PostgreSQL 管理状态与有界审计查询WorkerControlPlane 的 Register、Snapshot ACK、Runtime 心跳接收和 Redis 会话栅栏,以及 Gateway Outcome 上报的有界队列、序列确认与重试; Controller 的 Redis 共享 BASIC/EGRESS/TARGET 检查任务、按上游的有界轮转调度、HTTP/HTTPS/SOCKS5 Checker 探测和 Observation 状态归并Provider 连续空结果的代次化自动 Sequential 切换、禁用候选过滤、 末端 stop 的 CAS 路由停用和 Snapshot 即时刷新。
  • 部分完成Docker Compose/Kubernetes 运行时 mTLS Overlay。
  • 待完成:故障演练和代表性集群压测;现有 HTTP、CONNECT 长连接和 Extract 场景只提供可复现的负载工具,不构成容量验证结论。

检查项数量不等于生产就绪度。静态部署清单与 protobuf descriptor 验证也不代表 端到端拓扑已经完成;100,000 QPS 仍只是待验证的集群设计目标。

快速开始

前置条件为 Go 1.26、PowerShell以及用于 fixture 测试的 Docker。先在当前 PowerShell 会话设置本地占位凭据;这些值仅用于本地验证:

$env:PROXY_POOL_GATEWAY_PASSWORD = "LOCAL_GATEWAY_PASSWORD"
$env:PROXY_POOL_EXTRACT_TOKEN = "LOCAL_EXTRACT_TOKEN"
$env:PROXY_POOL_ADMIN_TOKEN = "LOCAL_ADMIN_TOKEN"
$env:PROVIDER_A_TOKEN = "LOCAL_PROVIDER_A_TOKEN"
$env:PROVIDER_B_TOKEN = "LOCAL_PROVIDER_B_TOKEN"
$env:PROXY_POOL_CONFIG_FINGERPRINT_KEY = "LOCAL_HIGH_ENTROPY_KEY_AT_LEAST_32_BYTES"

PROXY_POOL_CONFIG_FINGERPRINT_KEY 在 Admin 启用时必须至少为 32 字节,并与业务 Secret 分离管理。

校验配置并执行仓库验证:

go run ./deploy/tools/configcheck deploy/config/local.yaml
./scripts/verify.ps1

Redis、PostgreSQL 和 Controller fixture 脚本会使用 Docker 启动隔离依赖:

./scripts/test-redis.ps1
./scripts/test-postgres.ps1
./scripts/test-controller.ps1

PostgreSQL 与 Redis 是 Controller 的启动依赖。当前可运行的 Controller 入口如下, 将 CONFIG_FILE 替换为实际配置路径,并确保其中的 PostgreSQL 与 Redis 地址可从 进程所在网络访问:

go run ./cmd/proxy-controller -config CONFIG_FILE

deploy/config/local.yaml 面向 Compose 网络,默认使用 服务名 postgresredis;它可直接用于配置校验,但宿主机执行 go run 时需要 改用宿主机可达的存储地址。

本地配置中的 .invalid Provider URL 是故障演示占位,不会提供真实代理。 Gateway 已提供启动命令;需要先启用 Controller controlPlane 并配置匹配的 mTLS 证书(回环 fixture 可使用明文),再提供独立的拨号地址和 Worker 身份:

go run ./cmd/proxy-gateway -config CONFIG_FILE `
  -control-plane CONTROLLER_HOST:8443 `
  -cluster-id CLUSTER_ID -worker-id WORKER_ID `
  -instance-id INSTANCE_ID -zone ZONE

以上参数也可通过 PROXY_POOL_CONTROL_PLANE_ADDRESSPROXY_POOL_CLUSTER_IDPROXY_POOL_WORKER_IDPROXY_POOL_INSTANCE_IDPROXY_POOL_ZONE 提供。 Gateway 的 /livez/readyz/metrics 使用配置中的 metrics.listen;无有效 Snapshot 时 /readyz 返回 503。Checker 使用独立的逻辑/实例身份拉取有界任务:

go run ./cmd/proxy-checker -config CONFIG_FILE `
  -control-plane CONTROLLER_HOST:8443 `
  -checker-id CHECKER_ID -instance-id INSTANCE_ID `
  -max-in-flight 64

Checker 的参数也可通过 PROXY_POOL_CONTROL_PLANE_ADDRESSPROXY_POOL_CHECKER_IDPROXY_POOL_CHECKER_INSTANCE_IDPROXY_POOL_CHECKER_MAX_IN_FLIGHT 提供。它不会访问 Redis/PostgreSQL生产 Controller 在启用控制面时装配 Redis 共享任务 broker并按启用的 Upstream 调度 HTTP/HTTPS/SOCKS5 BASIC 检查、按每个 check.urls 创建 EGRESS 任务,并按启用 Routing 的 check.targets 创建 TARGET 任务。调度监督器每轮读取已发布配置,因此 reload 后的上游/路由启停、 检查间隔、抖动、超时、重试次数、maxInFlight、EGRESS URL 和 TARGET Profile 都会在下一轮生效; BASIC、EGRESS 与 TARGET 以有界轮转组共享上游并发上限。新启用的上游无需重启 Controller。 EGRESS 对成功响应提取纯文本 IP 或常见 JSON IP 字段并将其作为全局健康事实回传TARGET 事实 仅归并到对应的 (routing_name, target_url) Profile不改变 Proxy 全局健康。

proxy-loadgen 的 HTTP 场景可按固定请求数或固定时长运行,并将 HTTPS 目标经 Gateway 的请求交给标准 HTTP Transport 建立 CONNECT

go run ./cmd/proxy-loadgen `
  -target https://TARGET_URL/health `
  -proxy http://GATEWAY_HOST:8080 `
  -requests 10000 -concurrency 128 -timeout 10s

CONNECT 长连接场景直接向 HTTP Gateway 发起隧道握手,并在成功后保持每条隧道指定 时长;-timeout 只限制 TCP 连接与 CONNECT 响应,-hold 控制建连后的保持时间:

go run ./cmd/proxy-loadgen `
  -scenario connect -target https://TARGET_URL/ `
  -proxy http://GATEWAY_HOST:8080 `
  -requests 1000 -concurrency 128 -timeout 5s -hold 30s

使用 -duration 30s -rate 5000 可运行限速场景;省略 -rate 时固定数量 worker 会饱和发送。普通 HTTP 场景中,-method、重复的 -header-body 可组合用于 Distribution 的提取接口:

go run ./cmd/proxy-loadgen `
  -target http://CONTROLLER_HOST:8081/api/v1/proxies/extract `
  -method POST -header "Content-Type: application/json" `
  -header "X-API-Key: DISTRIBUTION_API_KEY" -body '{"count":1}' `
  -requests 1000 -concurrency 32 -timeout 10s

extract 场景则自动构造 POST 请求、每请求独立的 X-Request-IDIdempotency-Key,并只校验响应的 requestId、数量和同响应内代理 ID 唯一性:

go run ./cmd/proxy-loadgen `
  -scenario extract `
  -target http://CONTROLLER_HOST:8081/api/v1/proxies/extract `
  -header "X-API-Key: DISTRIBUTION_API_KEY" `
  -requests 1000 -concurrency 32 -timeout 10s `
  -extract-count 1 -extract-fulfillment partial

命令输出 JSON 报告,包含成功/失败分类、TunnelsEstablishedExtractResponsesValidatedExtractReturnedExtractValidationFailuresRateStartsGeneratedRateStartsDropped、固定内存的 连接握手延迟分位上界、吞吐和 Go 运行时内存/GC 快照。它不会输出提取响应中的地址或 凭据,也不构成 100,000 QPS 证明。限速场景以 Requests 表示实际发起数;当 RateStartsDropped 非零时,目标速率受压测端并发容量或时间窗限制,报告吞吐不得 标注为已达到配置的 -rate。每个生成的限速令牌均会计入实际发起或丢弃,因此 RateStartsGenerated = Requests + RateStartsDropped。 需要保留单次容量证据时,使用 -output REPORT_FILE 同时写出 JSON 文件;文件在 同目录完整写入后才替换目标,标准输出仍保留相同报告,便于交给日志或指标系统。

关键配置与入口

  • 本地配置完整配置参考
  • Distribution API:默认本地入口 http://127.0.0.1:8081
  • Admin API:默认本地入口 http://127.0.0.1:8082
  • Controller Metrics默认本地入口 http://127.0.0.1:9090,提供 /livez/readyz/metrics
  • 控制面协议Worker/Checker 的 protobuf 契约与 已验证的有界任务领取/Observation 上报边界
  • 运维手册:依赖、探针、发布边界与故障处置

核心不变量

  1. Gateway 热路径只读节点内存,不访问 PostgreSQL、Redis 或 Provider API。
  2. Proxy 容量使用 Reserved -> Active 原子转换,禁止超卖。
  3. Distribution 成功时原子执行 AVAILABLE -> EXTRACTED;提取后不归还、不续租。
  4. pool.maxSize 是当前未提取库存硬上限;fetch.maxTotal 是 Redis generation 内的累计获取停止阈值。
  5. CONNECT 向客户端提交 200 后不透明重放。
  6. 公开监听必须有认证或 CIDR 访问保护。
  7. PostgreSQL 只保存管理面状态Proxy 明细只存在于 Redis 短 TTL 活动池和节点 内存Redis 中的短期状态可由 Provider 重建。

路线图

  • P0 - Worker 控制面闭环Worker session、Snapshot ledger、ACK、运行态接收、 ownership 索引,以及 Gateway 快照客户端。
  • P0 - Checker 健康链BASIC/EGRESS/TARGET 的共享调度、实际探测、Observation reducer 和 FETCHED -> AVAILABLE / SUSPECT / UNHEALTHY 状态链已完成;可配置的持续 UNHEALTHY 回收会自动为已分配项发起带健康/归属栅栏的 Drain待 Snapshot ACK 与运行态归零后再删除; TARGET 事实按路由目标 Profile 独立归并。
  • P1 - Gateway 与 RoutingGateway 进程、快照凭据分发、五种 Routing 策略与 onUnavailable 已接入;上游停用会从后续完整 Snapshot 排除,并对现有 Worker ownership 发起带策略 revision 栅栏的 Drain。Routing 切换立即刷新在线 Worker 的 完整快照Sequential 的新分配切到新上游,旧 Proxy 与既有连接自然排空。动态容量 调整仍待完成。
  • P1 - 可观测与部署:低基数业务指标、完整 Compose/Kubernetes 进程拓扑, 以及故障转移和恢复演练。
  • P2 - 容量证明proxy-loadgen、HTTP/CONNECT/Extract 分场景压测,以及 可复现的代表性 100,000 QPS 集群报告。

文档导航

设计与需求

开发与 API

部署与运维

审计与测试