docs: record worker runtime capacity delivery

This commit is contained in:
youfak 2026-07-30 15:46:27 +08:00
parent 45ba6fb958
commit d648ba37e0
8 changed files with 113 additions and 12 deletions

View File

@ -63,10 +63,14 @@ var _ activitypool.HealthStore = (*Adapter)(nil)
var _ activitypool.InventoryReader = (*Adapter)(nil) var _ activitypool.InventoryReader = (*Adapter)(nil)
var _ extraction.Store = (*Adapter)(nil) var _ extraction.Store = (*Adapter)(nil)
var _ ownership.Repository = (*Adapter)(nil) var _ ownership.Repository = (*Adapter)(nil)
var _ workerruntime.SessionWriter = (*Adapter)(nil)
var _ workerruntime.ReportWriter = (*Adapter)(nil)
var _ workerruntime.RuntimeReader = (*Adapter)(nil)
var _ pool.InventoryReader = (*Adapter)(nil)
``` ```
Provider、Checker、Distribution 和 Ownership 只依赖各自需要的端口,不直接 Provider、Checker、Distribution、Ownership 和 Worker Runtime 只依赖各自需要
依赖 Redis 客户端、键名、Lua 返回格式或清理策略。 的端口,不直接依赖 Redis 客户端、键名、Lua 返回格式或清理策略。
`ownership.Repository` 改为适合远程存储的上下文感知接口: `ownership.Repository` 改为适合远程存储的上下文感知接口:
@ -97,6 +101,11 @@ pp:{activity}:owners HASH proxyID -> ownership assignment
pp:{activity}:owner-expiry ZSET proxyID -> ownership expiry milliseconds pp:{activity}:owner-expiry ZSET proxyID -> ownership expiry milliseconds
pp:{activity}:epoch STRING ownership 全局递增代次 pp:{activity}:epoch STRING ownership 全局递增代次
pp:{activity}:inventory HASH upstreamID -> 当前未提取库存 pp:{activity}:inventory HASH upstreamID -> 当前未提取库存
pp:{activity}:worker-sessions HASH workerID -> 当前 Worker session
pp:{activity}:worker-session-expiry ZSET workerID -> session expiry milliseconds
pp:{activity}:worker-runtime HASH workerID -> 完整稀疏运行态报告
pp:{activity}:worker-runtime-expiry ZSET workerID -> report expiry milliseconds
pp:{activity}:owned:<digest> ZSET 单 Upstream 已分配 AVAILABLE Proxy
pp:{activity}:idem:<digest> STRING 带 TTL 的提取幂等结果 pp:{activity}:idem:<digest> STRING 带 TTL 的提取幂等结果
pp:{activity}:op:<digest> STRING 带 TTL 的内部操作结果 pp:{activity}:op:<digest> STRING 带 TTL 的内部操作结果
``` ```
@ -167,6 +176,38 @@ Assign、Renew、BeginDrain 和 AcknowledgeDrain 分别使用有界小脚本,
- Assign 与 Extract 并发竞争同一 Proxy 时,只允许一个操作成功。 - Assign 与 Extract 并发竞争同一 Proxy 时,只允许一个操作成功。
- Expire 使用 `limit` 分批回收过期 assignment禁止无界返回。 - Expire 使用 `limit` 分批回收过期 assignment禁止无界返回。
### Worker 运行态与容量汇总
Gateway 的 `Capacity` 使用一次打包原子读取取得同一时刻的 Active/Reserved
`snapshot.Store` 周期生成完整稀疏报告。当前 Snapshot 已移除但仍有活动连接的
Proxy 继续以 `draining=true` 上报,直到 Active/Reserved 同时归零。
Redis Adapter 在单个 `{activity}` 原子边界内维护 Worker session 和运行态报告:
1. 新 Worker session 替换旧 session并隔离旧实例后续写入。
2. session 保存 Controller 已 ACK 的 snapshot version 与 ownership epoch报告
必须与 ACK 上界完全一致,不能通过自报超前 epoch 绕过所有权校验。
3. `report_sequence` 严格递增;同序号、同内容可幂等重放,冲突或倒序拒绝。
4. 非零计数必须匹配当前 Proxy owner、Worker ID 和 ownership epoch。
5. session/report TTL 使用 Redis 服务端时间;过期、缺失或损坏时容量 fail-closed。
6. 空报告清除该 Worker 的全部旧计数,稀疏报告中缺失的 Proxy 计数视为零。
`pool.InventoryReader` 低频返回单个 Upstream 的 `Managed`
`AvailableSlots`。Managed 统计 FETCHED/CHECKING/AVAILABLE/SUSPECT/DRAINING
Available Slots 只统计超过 safety margin、状态为 AVAILABLE 且所有权与新鲜
Worker 运行态一致的 `max - active - reserved`。未分配 Proxy 可直接贡献 Max
已分配但运行态未知的 Proxy 贡献零槽位。PostgreSQL 不保存这些短效报告或容量
明细Gateway 每次请求也不访问 Redis。
Managed 直接读取现有 Upstream 权威计数Available Slots 只扫描目标 Upstream
的未分配可用索引与已分配可用索引,不扫描全局 Proxy也不受其他供应商活记录
数量影响。索引成员数超过单次扫描预算时直接返回不可用,不降级为近似容量。
生产规模验收仍需验证脚本 p95/p99、CPU、内存和过期风暴下的有界行为。
Gateway `snapshot.Store` 扫描有界的当前 Snapshot并使用分片索引补充已移除但
仍非零的 runtime不扫描全部历史 Proxy历史 Capacity 注册表设硬上限,达到
上限时拒绝新 Snapshot 并保持旧视图,避免长期轮换造成无界内存增长。
### 短 TTL 清理 ### 短 TTL 清理
Redis Hash 字段没有独立 TTL因此使用三层有界清理 Redis Hash 字段没有独立 TTL因此使用三层有界清理
@ -226,6 +267,8 @@ Redis `inventory` 是当前未提取 Proxy 数量的运行时真值:
- Assign 与 Extract 并发互斥,以及 renew/drain/ACK/expire。 - Assign 与 Extract 并发互斥,以及 renew/drain/ACK/expire。
- 提交后连接断开、脚本缓存丢失、上下文取消和 Redis 不可用。 - 提交后连接断开、脚本缓存丢失、上下文取消和 Redis 不可用。
- 30 秒 TTL 持续写入下的有界清理与库存一致性。 - 30 秒 TTL 持续写入下的有界清理与库存一致性。
- Worker session 替换、运行态序号幂等/冲突、报告过期和 ownership epoch 隔离。
- 权威 Managed/Available Slots 聚合及扫描预算耗尽时的 fail-closed 行为。
Lua 语义必须使用真实 Redis 8.2 集成测试验证。单元测试最长 60 秒,并执行 Lua 语义必须使用真实 Redis 8.2 集成测试验证。单元测试最长 60 秒,并执行
gofmt、go vet、全量测试、构建和 diff whitespace 检查。100,000 QPS 只能由 gofmt、go vet、全量测试、构建和 diff whitespace 检查。100,000 QPS 只能由

View File

@ -34,6 +34,18 @@ sequenceDiagram
`worker_id` 是逻辑节点,`instance_id` 区分进程重启,`session_id` 防止旧进程 `worker_id` 是逻辑节点,`instance_id` 区分进程重启,`session_id` 防止旧进程
继续上报。所有权 `epoch` 小于 Controller 当前值的数据必须拒绝。 继续上报。所有权 `epoch` 小于 Controller 当前值的数据必须拒绝。
`ReportRuntimeRequest.report_sequence` 在当前 `session_id` 内严格单调递增。
相同序号只允许内容完全相同的幂等重放;较小序号或相同序号的不同内容必须
拒绝。`observed_at` 只用于观测,不作为乱序判定依据,运行态 TTL 统一使用
Controller 侧 Redis 服务端时间。session 同时保存 Controller 已接受的
`snapshot_version/ownership_epoch`;运行态报告必须与该 ACK 上界完全一致,
Worker 自报的超前版本或 epoch 也必须拒绝。
运行态上报是完整稀疏替换:只携带 Active/Reserved 非零的 Proxy空列表表示
当前会话全部归零。Controller 只有在 Worker session、报告 TTL、Proxy ownership
和 ownership epoch 同时有效时才使用计数;报告缺失、过期或不一致时按零可用
容量 fail-closed不能把未知计数解释成空闲容量。
## 3. Snapshot 与 Delta ## 3. Snapshot 与 Delta
完整 Snapshot 包含: 完整 Snapshot 包含:

View File

@ -143,6 +143,15 @@ type Proxy struct {
运行态 `active``reserved` 存在 Worker 本地、按 Proxy ID 分片,不写入 运行态 `active``reserved` 存在 Worker 本地、按 Proxy ID 分片,不写入
不可变 Snapshot。 不可变 Snapshot。
Worker 以有界周期批量上报运行态,而不是在每个 Gateway 请求上写 Redis。
报告通过公用 `workerruntime` seam 表达为完整稀疏替换Gateway 从打包原子计数
读取同一时刻的 Active/Reserved已从当前 Snapshot 移除但仍有连接的 Proxy
继续以 draining 状态上报。Controller 使用 session、单调 report sequence、
ownership epoch、Controller 已 ACK 的 snapshot/epoch 上界和 Redis 服务端 TTL
共同校验;缺失、过期或超前报告按零可用容量 fail-closed。运行态报告扫描有界
当前 Snapshot并以分片索引补充已移除但仍非零的 runtime历史 Capacity
注册表有硬上限,避免短 TTL Proxy 持续轮换导致心跳扫描与内存无界增长。
## 6. Proxy 状态机 ## 6. Proxy 状态机
```mermaid ```mermaid
@ -244,6 +253,13 @@ flowchart TD
fail-closed不回退为本地 Leader。补池使用 minimum/target 双水位迟滞,库存 fail-closed不回退为本地 Leader。补池使用 minimum/target 双水位迟滞,库存
复核期间若仍有 pending Fetch则等待下一轮再同步 Managed避免重复计数。 复核期间若仍有 pending Fetch则等待下一轮再同步 Managed避免重复计数。
补池读取 `pool.InventoryReader` 返回的权威 `Managed``AvailableSlots`,不使用
AVAILABLE Proxy 数量乘固定并发的近似值。Available Slots 同时计入 Proxy 状态、
TTL safety margin、MaxConcurrency、Worker Active/Reserved 和当前 ownership
未知 Worker 运行态贡献零槽位。Redis 只扫描目标 Upstream 的未分配/已分配
AVAILABLE 索引Managed 读取已有权威计数;该读取属于 Controller 冷路径,
Gateway 热路径仍只访问本地 Snapshot 和本地原子计数。
### 8.1 Empty、Duplicate 与 Error ### 8.1 Empty、Duplicate 与 Error
- **Empty**HTTP/认证成功、模板执行成功,解析后合法 Proxy 数为 0。 - **Empty**HTTP/认证成功、模板执行成功,解析后合法 Proxy 数为 0。

View File

@ -219,8 +219,15 @@ generation + epoch fence、全局 requestInterval、全局 maxInFlight Permit、
回收及 Redis 状态丢失后的新 generation 自动重建Redis 异常期间不发放请求。 回收及 Redis 状态丢失后的新 generation 自动重建Redis 异常期间不发放请求。
补池配置新增必填 `refill` 双水位和 `fetch.estimatedIPsPerCall`Pool Reconciler 补池配置新增必填 `refill` 双水位和 `fetch.estimatedIPsPerCall`Pool Reconciler
已实现迟滞与 pending 槽位折算FetchBudget 仅在无 pending 时同步 Redis 权威 已实现迟滞与 pending 槽位折算FetchBudget 仅在无 pending 时同步 Redis 权威
Managed。Provider Fleet、Worker Active/Reserved 汇总和 bootstrap 接线仍待完成, Managed。Gateway 已增加打包原子 Active/Reserved 读取与完整稀疏运行态快照;
因此本轮不勾选 Task 10 的组合验收项。 公用 `workerruntime` session/report/read seam 同时提供并发安全内存参考实现和
生产 Redis Adapter。Redis 以服务端时间、Worker session、已 ACK snapshot/epoch、
单调 report sequence 和报告 TTL 原子隔离旧实例,并由 `pool.InventoryReader` 汇总
权威 Managed/Available Slots真实 Redis 8.2 已覆盖空报告、幂等重放、倒序、
冲突、超前 epoch、过期、单 Upstream 扫描隔离和预算耗尽的 fail-closed 行为。
WorkerControlPlane gRPC 接收端、
session 签发/心跳、Snapshot ACK 账本、Provider Fleet/bootstrap、全局
`fetch.maxTotal` 和健康执行链仍待完成,因此本轮不勾选 Task 10 的组合验收项。
## Task 11: Checker and Health Reducer ## Task 11: Checker and Health Reducer

View File

@ -46,7 +46,7 @@
| PROXY-002 | 唯一键包含 scheme、host、port、username、credentialVersion | 6655-6727, 8605-8678 | 去重单测 | | PROXY-002 | 唯一键包含 scheme、host、port、username、credentialVersion | 6655-6727, 8605-8678 | 去重单测 |
| PROXY-003 | TTL 来源优先级明确并统一 UTC | 681-747, 8655-8678 | TTL 表驱动测试 | | PROXY-003 | TTL 来源优先级明确并统一 UTC | 681-747, 8655-8678 | TTL 表驱动测试 |
| CAP-001 | Gateway 分配使用 Reserved -> Active 原子转换 | 1203-1467, 8530-8597 | 固定 Max 下打包 CAS 与 1,000 并发不超卖已完成;动态降容和完整生命周期证据待完成 | | CAP-001 | Gateway 分配使用 Reserved -> Active 原子转换 | 1203-1467, 8530-8597 | 固定 Max 下打包 CAS 与 1,000 并发不超卖已完成;动态降容和完整生命周期证据待完成 |
| CAP-002 | 补池依据 Available Slots不只看 Proxy 数量 | 1203-1402, 8530-8597 | `AvailableSlots`、显式 minimum/target 水位、pending 槽位和迟滞 Reconciler 已测试;Worker Active/Reserved、ownership、目标健康及 Gateway reserve 运行时聚合待完成 | | CAP-002 | 补池依据 Available Slots不只看 Proxy 数量 | 1203-1402, 8530-8597 | `AvailableSlots`、显式 minimum/target 水位、pending 槽位和迟滞 Reconciler 已测试;Gateway 打包 Active/Reserved 报告、Worker session/ACK/sequence/TTL/ownership fence、单 Upstream 索引及 Redis 权威 Managed/Slots 汇总已通过内存与真实 Redis 测试WorkerControlPlane 接线、目标健康和 Gateway reserve 策略仍待完成 |
| CAP-003 | pool.maxSize 包括 FETCHED/CHECKING/AVAILABLE/SUSPECT/DRAINING 与 pending expected | 3001-3533, 6642-6680 | `FetchBudget` 100 并发额度预占测试 | | CAP-003 | pool.maxSize 包括 FETCHED/CHECKING/AVAILABLE/SUSPECT/DRAINING 与 pending expected | 3001-3533, 6642-6680 | `FetchBudget` 100 并发额度预占测试 |
| CAP-004 | TTL safety margin 内禁止新分配 | 173-220, 6728-6741 | 时钟测试 | | CAP-004 | TTL safety margin 内禁止新分配 | 173-220, 6728-6741 | 时钟测试 |
| CAP-005 | 多 Worker 不在热路径访问 Redis 计数 | 1403-1467 | Gateway 包依赖审计、Snapshot/Dispatch 测试 | | CAP-005 | 多 Worker 不在热路径访问 Redis 计数 | 1403-1467 | Gateway 包依赖审计、Snapshot/Dispatch 测试 |

View File

@ -74,16 +74,17 @@ soak 测试单独标记,不混入快速单测。
## 5. 当前本地微基准 ## 5. 当前本地微基准
2026-07-28Windows/amd64、Intel Core Ultra 7 155H 2026-07-30Windows/amd64、Intel Core Ultra 7 155H
```text ```text
BenchmarkAcquire100kIndexed-22 3553592 640.0 ns/op 256 B/op 2 allocs/op BenchmarkAcquire100kIndexed-22 1000000-1867125 893.9-1047 ns/op 256 B/op 2 allocs/op
BenchmarkStoreApply100k-22 1 472.7 ms/op 654 MB/op 2700642 allocs/op BenchmarkStoreApply100k-22 1 518.7 ms/op 540 MB/op 3000887 allocs/op
``` ```
`Acquire` 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。 `Acquire` 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。
`Store.Apply` 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配, `Store.Apply` 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配,
暂不自动回收曾出现过的 Proxy ID。后续需要基于 RCU/引用计数定义安全回收点。 暂不自动回收曾出现过的 Proxy ID但注册表有 1,000,000 项硬上限,达到上限时
拒绝新 Snapshot 并保留旧视图。后续需要基于 RCU/引用计数定义安全回收点。
这些数据不包含网络、认证、Provider、存储或多 Worker 协调,不能作为 这些数据不包含网络、认证、Provider、存储或多 Worker 协调,不能作为
100k QPS 端到端验收结论。 100k QPS 端到端验收结论。

View File

@ -2,6 +2,26 @@
## 2026-07-30 ## 2026-07-30
- Gateway `Capacity` 新增一次打包原子读取,`snapshot.Store` 可生成完整稀疏
Active/Reserved 运行态报告;当前快照已移除但仍有连接的 Proxy 会持续以
draining 上报,归零后从后续报告消失。
- 新增公用 `workerruntime` session/report/read seam 与并发安全 MemoryStore
完整替换、空报告清零、session fencing、单调 sequence、同内容幂等重放、
冲突/倒序拒绝和 TTL fail-closed 均已有单测。
- 生产 `redisactivity` Adapter 新增 Worker session/运行态 Lua 和权威
`pool.InventoryReader`Managed/Available Slots 原子计入状态、TTL safety、
MaxConcurrency、ownership 及 Active/Reserved未知或过期运行态贡献零容量。
- 真实 Redis 8.2 已覆盖 ACK snapshot/epoch、旧 session、空报告、超前 epoch、
报告过期、扫描预算耗尽及容量聚合。Managed 使用已有权威计数Available
Slots 只扫描目标 Upstream 的未分配/已分配可用索引Gateway 报告扫描当前
Snapshot并用分片索引补充已移除但仍非零的 runtime历史注册表设置硬上限。
WorkerControlPlane 接收端、Provider
Fleet/bootstrap、全局 `fetch.maxTotal` 和健康执行链仍待完成,总验收计数保持
51/73。
- Gateway 当前 Proxy 禁用活跃索引回调,只有移出 Snapshot 后才开启分片追踪;
本机 100k Proxy `Acquire` 三轮 1 秒基准为 893.9-1047 ns/op、256 B/op、
2 allocs/op。该数据只证明本地调度微基准不代表 100k QPS 集群验收。
- 新增公用 Provider `Coordinator.RunLeader` / `LeaderSession` 深 seam 和独立 - 新增公用 Provider `Coordinator.RunLeader` / `LeaderSession` 深 seam 和独立
`redisprovider` AdapterRedis Lua 原子维护 generation、epoch、Leader 租约、 `redisprovider` AdapterRedis Lua 原子维护 generation、epoch、Leader 租约、
全局 requestInterval 与带 TTL 的 maxInFlight Permit异常时 fail-closed。 全局 requestInterval 与带 TTL 的 maxInFlight Permit异常时 fail-closed。

View File

@ -35,7 +35,8 @@
机器契约和文档类滞后勾选已按仓库证据校正 机器契约和文档类滞后勾选已按仓库证据校正
13. [进行中] 落地 `proxy-controller` 进程装配配置单次加载、PostgreSQL 迁移、 13. [进行中] 落地 `proxy-controller` 进程装配配置单次加载、PostgreSQL 迁移、
Redis 活动池、低基数状态聚合、Distribution/Admin/Metrics 启动与关闭已完成, Redis 活动池、低基数状态聚合、Distribution/Admin/Metrics 启动与关闭已完成,
双存储 bootstrap 和探针集成已通过Provider、业务指标与完整容器进程链仍待实现 双存储 bootstrap 和探针集成已通过Worker 运行态存储与权威容量读取原语已
完成WorkerControlPlane、Provider、业务指标与完整容器进程链仍待实现
## 串并行关系 ## 串并行关系
@ -57,7 +58,8 @@
- Docker Compose 配置与 Kubernetes Kustomize 已完成静态渲染验证Redis 8.2 - Docker Compose 配置与 Kubernetes Kustomize 已完成静态渲染验证Redis 8.2
与 PostgreSQL 18 的隔离 Adapter fixture 已运行,完整目标运行拓扑尚未启动。 与 PostgreSQL 18 的隔离 Adapter fixture 已运行,完整目标运行拓扑尚未启动。
- `cmd/proxy-controller` 已实现 Admin/Distribution/Metrics 与双存储启动装配; - `cmd/proxy-controller` 已实现 Admin/Distribution/Metrics 与双存储启动装配;
Gateway、Checker、Loadgen、Provider Leader/分布式限流、业务指标、Redis Provider 分布式协调和 Worker 运行态 Redis 原语已完成,但 WorkerControlPlane
故障转移验证与代表性集群压测属于后续实施范围。 接收端、Provider Fleet、Gateway、Checker、Loadgen、业务指标、Redis 故障
转移验证与代表性集群压测属于后续实施范围。
- `implementation-plan.md` 当前按 73 个验收项统计;已校正为 51 项完成, - `implementation-plan.md` 当前按 73 个验收项统计;已校正为 51 项完成,
验收项完成率约 69.9%,不等同于生产就绪度。 验收项完成率约 69.9%,不等同于生产就绪度。