11 KiB
配置参考
1. 加载规则
主配置格式为 YAML,根字段 version 当前固定为 1。加载器启用严格字段
检查,拼写错误或未来版本字段不会被静默忽略。推荐启动命令显式传入配置路径:
go run ./cmd/proxy-controller -config configs/proxy-pool.yaml
所有时间值使用 Go duration,例如 500ms、30s、5m。示例中的
${TOKEN}、${PASSWORD}、${POSTGRES_URL} 等由加载器从同名环境变量
展开;这些值不得写入日志、指标、配置转储或错误响应。生产配置优先使用
环境变量或 Secret 文件,不提交明文值。
加载与热更新必须遵循同一顺序:
读取文件 -> 严格解析 -> 字段校验 -> 引用/正则校验
-> 构建不可变快照 -> 计算差异 -> 原子替换
新配置任何一步失败时保留旧快照。删除或禁用 Upstream 只停止新 Fetch 和新 分配,已有连接进入 Drain,不强制中断。
2. 根结构
version: 1
defaults: {}
security: {}
gateway: {}
distribution: {}
admin: {}
metrics: {}
storage: {}
routing: []
upstreams: {}
defaults:Fetch 与 Check 的公共建议值。生产配置仍建议在每个启用的 Upstream 显式写出关键限制,避免继承关系不清。security:跨入口启动保护。gateway:HTTP/HTTPS CONNECT 数据面入口。distribution:一次性独占提取入口。admin:运维管理入口,必须与 Distribution 分端口。metrics:Prometheus 入口。storage:Controller 使用的 PostgreSQL 与 Redis 地址。routing:有序 Routing 列表,自上而下首条命中停止。upstreams:全局共享的 Upstream 运行时定义。
3. 安全与监听器
security:
requireProtectionOnPublicListen: true
启用严格保护时,只要 Gateway、Distribution 或 Admin 满足以下全部条件, 启动即失败:
- 入口已启用且监听地址不是回环地址。
auth.mode: none。access.allowCIDRs为空。
监听器公共字段:
enabled: true
listen: 0.0.0.0:8081
access:
allowCIDRs: [10.0.0.0/8]
trustedProxies: [10.10.0.10/32]
auth:
mode: apiKey
header: X-API-Key
token: "${DISTRIBUTION_API_KEY}"
limits:
maxConcurrentConnections: 100000
requestsPerMinute: 6000
requestsPerMinutePerClient: 600
trustedProxies 只决定何时接受 Forwarded 或 X-Forwarded-For,不能替代
allowCIDRs。来自非可信代理的转发头必须忽略。
3.1 认证模式
none:无身份认证,访问控制与限流仍生效。usernamePassword:使用username和password。apiKey:使用header和token。ipWhitelist:使用cidrs。any:methods中任一方法成功即可;方法字段名仍是mode。
Gateway、Distribution 与 Provider API 的认证是三套独立边界。改变其中一套 不得连带改变另外两套。
4. Gateway
gateway:
enabled: true
listen: 127.0.0.1:8080
auth: {mode: none}
limits:
maxConcurrentConnections: 50000
retry:
maxAttempts: 2
retryMethods: [GET, HEAD]
destinationPolicy:
denyPrivateNetworks: true
denyLoopback: true
denyLinkLocal: true
denyCIDRs: [169.254.169.254/32]
allowedPorts: [80, 443]
retryMethods默认只应包含幂等方法。POST、PUT、PATCH、DELETE 不自动重试。- CONNECT 向 Client 写出
200 Connection Established后不透明重放。 - 目的地址策略必须在 DNS 解析前后都执行,防止 DNS Rebinding。
- 三个
deny*字段省略时均按true处理;只有显式配置为false才放行 对应类别,部分配置不会改变其他类别的安全默认值。 allowedPorts省略时安全默认值为[80, 443];配置空列表不表示开放全部端口。- 保留地址、CGNAT 与云元数据端点始终拒绝,不能通过私网/链路本地开关放行。
maxConcurrentConnections是入口准入上限,不是 Proxy 容量上限。
5. Distribution
distribution:
enabled: true
listen: 127.0.0.1:8081
auth: {mode: none}
clientIdentification: {mode: sourceIP}
limits:
requestsPerMinute: 60
requestsPerMinutePerClient: 30
extraction:
fulfillment: partial
maxCountPerRequest: 20
minRemainingTTL: 30s
maxHealthCheckAge: 15s
reserveForGateway: 5
Extraction 是固定的一次性独占行为,没有 mode、leaseDuration、
release 或 renew 配置。事务提交后执行 AVAILABLE -> EXTRACTED,该 Proxy
不再由 Gateway 或 Distribution 分配。
fulfillment:partial或allOrNothing,默认语义为partial。maxCountPerRequest:单次请求硬上限。minRemainingTTL:剩余寿命低于此值时不参与提取。maxHealthCheckAge:最近检查早于此窗口时不参与提取。reserveForGateway:提取后必须留给 Gateway 的最低符合条件库存数量。
partial 会提交实际可得数量;allOrNothing 数量不足时事务回滚,一个也不
提取。认证关闭时仍应使用 sourceIP 识别匿名 Client 并执行全局/来源限流。
6. Routing
routing:
- name: api-post
enabled: true
purpose: gateway
match:
hostRegex: '^api\\.example\\.com$'
methods: [POST]
pathRegex: '^/v1/'
headers: {X-Tenant: premium}
upstreams: [provider-a, provider-b]
strategy:
type: sequential
switchAfterEmptyFetch: 5
endBehavior: stayLast
onUnavailable:
action: reject
waitTimeout: 0s
- Routing 列表有序,首条匹配后停止。
purpose为gateway或extract。strategy.type支持sequential、random、roundRobin、weighted、leastConnections。weighted使用weights映射,键必须引用本 Routing 的 Upstream。sequential必须设置大于零的switchAfterEmptyFetch。onUnavailable.action为reject、wait或direct;默认建议reject。
Sequential 的空计数属于 Upstream,当前索引属于 Routing。只有 Provider 响应 成功、模板成功且合法候选为零时才增加空计数。错误不改变空计数;重复候选 会重置空计数但增加独立 duplicate 指标。
7. Upstream
upstreams:
provider-a:
enabled: true
exposure: [gateway, extract]
provider:
billingMode: fetch
protocols: [http, https]
api:
url: https://provider-a.example/proxies
method: GET
auth:
type: apiKey
location: header
name: X-Provider-Key
value: "${PROVIDER_API_KEY}"
headers: {}
query: {count: '100'}
body: {type: json, value: {}}
template: '{{.}}'
proxyAuth: {type: response}
pool: {maxSize: 1000, shrinkDelay: 30s}
capacity: {maxConcurrencyPerProxy: 10}
lifecycle: {ttl: 2m, allocationSafetyMargin: 15s}
fetch:
requestInterval: 1s
timeout: 3s
maxAttempts: 3
maxInFlight: 1
maxTotal: 100000
maxResponseBytes: 1048576
templateTimeout: 100ms
retry: {initial: 500ms, max: 30s, jitter: 20}
check:
interval: 30s
jitter: 20
maxInFlight: 100
timeout: 2s
maxAttempts: 2
maxConsecutiveFailures: 3
urls: [http://connect.rom.miui.com/generate_204]
7.1 Provider 与代理认证
api.auth用于系统访问 Provider API。proxyAuth用于最终连接被获取的 Proxy。- Provider
api.auth.type支持none、basic、bearer、apiKey。 apiKey使用location: header|query与name、value,程序负责 Header 设置或 Query URL 编码。basic使用username、password;bearer使用token。proxyAuth.type: response表示凭据来自 Provider 响应。proxyAuth.type: static使用配置中的username、password。proxyAuth.type: ipWhitelist表示 Provider 按出口 IP 放行,不配置账号密码。
Provider API 认证不使用入口的 auth.mode,代理连接认证也不使用
mode。三者的字段和凭据不可互相回退:
# 对外 Distribution/Gateway/Admin
auth:
mode: apiKey
header: X-API-Key
token: "${CLIENT_API_KEY}"
# 请求 Provider API
auth:
type: bearer
token: "${PROVIDER_API_TOKEN}"
# 连接 Provider 返回的 Proxy
proxyAuth:
type: static
username: "${PROVIDER_PROXY_USER}"
password: "${PROVIDER_PROXY_PASSWORD}"
7.2 Pool 与累计额度
pool.maxSize:当前系统维护且尚未 EXTRACTED 的 Proxy 硬上限,包括 FETCHED、CHECKING、AVAILABLE、SUSPECT、DRAINING 和 pending expected。fetch.maxTotal:当前运行或计费周期内,从 Provider 成功获取的累计上限;0表示不设置累计上限。
fetch.maxTotal 不得小于 pool.maxSize。提取一个 Proxy 会释放当前库存位置,
但不会恢复累计获取额度。
7.3 Fetch 限制
requestInterval:同一 Provider 请求间隔。timeout:单次调用超时。maxAttempts:单次补池动作最大尝试次数。maxInFlight:同一 Provider 同时在途请求数。maxResponseBytes:读取响应的硬上限。templateTimeout:模板解析执行上限。retry:错误退避;HTTP 429 还必须尊重Retry-After。
大量缺池信号必须合并成 singleflight 或容量为 1 的通知,不能按 Gateway 请求 数量线性触发 Provider API。
7.4 生命周期与健康
- 明确绝对过期时间优先于响应 TTL,响应 TTL 优先于配置
lifecycle.ttl。 - 距离过期不足
allocationSafetyMargin时停止新分配。 check.jitter为调度抖动百分比,避免所有 Proxy 同时探测。- 第一次有意义失败进入 SUSPECT;达到
maxConsecutiveFailures后才进入 UNHEALTHY。
8. 存储、Admin 与 Metrics
admin:
enabled: true
listen: 127.0.0.1:8082
auth: {mode: none}
metrics:
enabled: true
listen: 127.0.0.1:9090
storage:
postgresURL: "${POSTGRES_URL}"
redisURL: "${REDIS_URL}"
PostgreSQL 是 Proxy 生命周期、Routing 选择、Worker 所有权和 Extraction Record 的权威存储。Redis 只承载可重建的短期协调状态,不能成为独占提取的唯一事实 来源。Metrics 标签禁止 Proxy IP、Client ID、Session、完整 URL 和 Request ID。
9. 启动前校验清单
version必须为1,未知字段拒绝。- 所有启用监听器具有合法
host:port。 - 非回环监听器满足认证或来源 CIDR 保护。
- Routing 名称唯一,正则可编译,引用的 Upstream 存在。
- Sequential 阈值大于零,
onUnavailable.action明确。 - 启用的 Upstream 有正数
pool.maxSize、并发和 Fetch 限制。 allocationSafetyMargin < ttl。fetch.maxTotal == 0或fetch.maxTotal >= pool.maxSize。- Distribution 的 fulfillment 合法,单次数量大于零。
- Secret 未写入日志可见配置转储。