- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
导读
本文围绕 2026-08-04-chat-lifecycle-soak-04-coordinator-verdict.md 展开,详解 WuKongIM 聊天生命周期(chat lifecycle)长时压测第四阶段的核心设计:如何在第四台专用主机上部署一个不持有任何流量 socket 的 Coordinator,协调三个独立 worker 完成固定压力(soak)与老化数据容量(aged-data capacity)两类运行,并为每个运行产出确定性的产品/测试框架判定(verdict)。读完本文,你将掌握 preflight 准入检查、固定组目录准备、worker 分配与全局速率授予、Channel 生命周期三态证明(loaded → 自然缺失 → reheat)、正确性/延迟/资源/集群四维阈值判定,以及连续 checkpoint 与脱敏报告生成的完整实现脉络。
该计划对应的实现已全部落地于仓库internal/bench/chatlifecycle/包(99 个 Go 文件),本文将把计划文档的每个任务步骤与真实源码逐一对应,做到"计划 + 实现 + 验证"三位一体。
一、总体架构:第四台主机的无流量 Coordinator
1.1 为什么需要独立的 Coordinator
计划的 Goal 明确要求三件事:
- 协调三个独立 worker:三个压测 worker 必须被统一编排,避免各自为政导致负载形状漂移;
- 证明可重复的全节点 Channel runtime 转换:即反复证明一个 Channel 在三个服务节点上先"加载",后"自然冷却消失",再通过真实 SEND 重新加载,且消息序号不中断;
- 产出确定性判定:固定压力运行与老化数据容量运行都要有明确的
product_failure/harness_invalid/infrastructure_failure/operator_stop等闭合分类,而非"压完看日志"。
为此,计划规定第四台主机专门运行 Coordinator。它的职责边界在 coordinator.go 中被实现为一条严格的状态机链:
preflight -> group setup -> worker assign -> worker start -> observe -> checkpoint/finalize与常见的"主节点即压测节点"方案不同,Coordinator不持有任何流量 socket,只做校验、调度、轮询与证据归约。这意味着:
- 原始身份(raw UID、具体 channel ID、bearer token、标记 payload)只存在于瞬时认证探针请求中;
- 持久化报告只使用hash 与 sample index,从报告本身无法还原任何用户身份或频道身份;
- Coordinator 进程崩溃不会导致流量失真,因为流量由三个 worker 独立承担。
1.2 技术栈与三个可插拔边界
计划列出的技术栈在源码中一一对应:
| 计划声明的技术要素 | 仓库实现位置 |
|---|---|
| Go Coordinator 状态机 | coordinator.go |
| 现有 target/metrics/bench API | internal/bench/target/client.go |
| Prometheus 文本解析 | disk_observer.go、cluster_observation.go、observer.go内嵌解析 |
| 受保护的 debug 端点 | preflight 中DebugConfig/DebugCluster/ForceGC调用 |
| node_exporter 文件系统指标 | preflight.go中DiskReader与node_filesystem_*解析 |
| worker HTTP 客户端 | worker_client.go |
| JSON 与 Markdown 报告 | report.go |
Coordinator 对外只暴露极窄的接口(CoordinatorPreflight、CoordinatorGroupSetup、CoordinatorWorker、CoordinatorObserver、CoordinatorRunHooks),运行层通过这些窄接口执行已验证的计划——这正是 doc.go 声明的包设计意图:"it intentionally contains no target mutation, concrete transport, worker loop, or host credential logic",即本包只负责确定性模型、窄启动编排、有界消息验证与脱敏证据记录。
二、配置模型与正式/本地默认值
2.1 三组运行语义:Profile / Mode / Stage
在 types.go 中,一次运行由三个正交维度定义:
- Profile:
formal(固定正式负载)或local(缩小规模、保留集群拓扑与同步语义的本地 shakeout); - Mode:
soak(执行配置好的生命周期长跑)或capacity(在老化 soak 证据之后进入容量阶梯); - Stage:
formal(完整正式观测窗口)、rehearsal(完整规模但有界彩排窗口)、shakeout(缩减的本地验证窗口)。
计划文档中提到的profile: local_shakeout,在实现中对应ProfileLocal + StageShakeout的组合(见 defaults.go 的LocalConfig())。此外Config还要求RunID非空、Seed非零(保证确定性随机流不依赖隐式种子),RunDuration是仅限 CLI 的彩排时长覆盖,仓库 YAML 无法设置它。
2.2 正式配置默认值一览
FormalConfig() 是经过评审的正式负载默认值,下面按维度列出(也是计划中各项阈值在实现中的落点):
| 维度 | 参数 | 正式默认值 |
|---|---|---|
| 规模 | 在线用户 | 10,000 |
| 规模 | 新增用户/天 | 250,000 |
| 规模 | 全局 SEND 速率 | 2,000 msg/s |
| 流量 | 人/群流量占比 | 90% / 10% |
| 热点集 | person / group 频道 | 8,000 / 2,000 |
| 拓扑 | 逻辑 Slot 组 / Hash Slot | 12 / 256 |
| 拓扑 | Slot 副本 / Channel 副本 | 3 / 3 |
| 容量 | 每节点最大频道数 | 50,000 |
| 组目录 | Small/Medium/Large/VeryLarge | 1,600 / 300 / 99 / 1(超大群 100,000 成员) |
| 时间线 | 预热 / checkpoint / 最终 | 2 小时 / 24 小时 / 72 小时 |
| 磁盘 | 最小数据文件系统 | 500 GB(500_000_000_000字节) |
| 磁盘 | 安全停止空闲百分比 | 5% |
| 正确性 | 整体首试失败率 | < 1/10,000 |
| 正确性 | 任意一分钟窗口首试失败率 | ≤ 1/1,000 |
| 延迟 | Hot SENDACK p99 / p99.9 | 400 ms / 1 s |
| 延迟 | Cold/reheat SENDACK p99 / p99.9 | 2 s / 5 s |
| 延迟 | 全量会话同步 p99 / p99.9 | 1 s / 3 s |
| 资源 | forced-GC live-heap 斜率 | 5% / 6 小时窗口 |
| 资源 | goroutine 斜率 | 5% / 24 小时窗口 |
| 集群 | 健康轮询 / 持续失败判负 | 5 s / 30 s |
| 集群 | 热 Slot 复制滞后上限 | 64 条 Raft entry |
| 集群 | Leader 不均衡阈值 | 20% / 10 分钟 |
说明:计划文档中 Hot SENDACK 的 p99 写的是 200 ms,当前仓库实现默认值为400 ms;数据文件系统下限计划写作 1,000,000,000,000 字节,实现默认值为500 GB。凡涉及阈值数值,以当前仓库 defaults.go 为准。
三、Task 1:正式 Preflight 与目标观测
计划第一阶段解决"流量开闸之前必须先证明环境合法"。实现分为 preflight(一次性准入)与 observer(连续观测)两条线。
3.1 拓扑与端点配置校验
preflight.go 的静态校验要求配置必须命名:
- 三个 service-node 的 metrics/debug 端点;
- 一个独立均衡的 HTTP API 观测池;
- 一个另行独立均衡的 TCP gateway 池(
GatewayTCPAddrs); - 三个 worker 端点;
- 三个 host-metrics 端点,外加一个单独的 load-host 端点。
计划明确要求:拒绝复用 worker/service 地址,拒绝把 API 池直接复制成 gateway 池。preflight 在发起任何网络 I/O 之前先完成静态拓扑校验(Check中cfg.Validate()与 bench token 非空即先决条件)。
3.2 最小化 debug/metrics 解码
preflight 对每个 service node 依次调用:
Healthz/Readyz:服务与就绪探活;DebugConfig:读取受保护的/debug/config,并与配置比对。matchesPreflightConfig精确断言12 个初始 Slot 组、256 个 hash slot、Slot 副本 3、Channel 副本 3、max_channels=50000(对应实现默认值);ForceGC:受保护的 forced-GC heap 触发,必须在指标抓取前执行,以保证 heap 样本干净;CheckMetrics:校验产品 Prometheus 指标(Go/process、运行时队列、Channel 激活拒绝、Channel 元数据创建)齐备;DebugCluster:读取/debug/cluster的 Slot leader/replica/ISR/lag 事实,与节点 ID 交叉核对。
计划强调"使用最小响应结构,避免 debug 端点未来新增字段破坏基准"——实现中所有解码都限定在最小的目标结构体集合内。
3.3 node_exporter 磁盘准入
preflight 通过DiskReader解析node_filesystem_avail_bytes与node_filesystem_size_bytes,按配置中显式给出的数据挂载点/设备标签(Mountpoint/Device)选取文件系统:
- 缺失或重复匹配→
harness_invalid(PreflightCodeDiskAmbiguous); - 低于 5% 空闲→
infrastructure_failure(PreflightCodeDiskFree),并触发CoordinatedStop安全协调停止; - 容量不足(小于
MinimumDataFilesystemBytes)→infrastructure_failure(PreflightCodeDiskCapacity)。
正式 profile 还额外要求 host/process 资源可观测(HostResourcesObserved、ProcessResourcesObserved及 systemd 进程角色校验),否则按disk_ambiguous拒绝。
3.4 五秒观测轮询与连续失败判定
observer.go 实现连续的集群健康观测:
- 每5 秒(
Observation.Cadence)轮询一轮 health/readiness/cluster 状态,一轮内三个节点的请求由独立 goroutine 并行发出; - 服务不可用连续 30 秒→
product_failure(ObserverCodeServiceHealth); - 每个逻辑 Slot 组必须有 1 个 leader 与 3 个副本,热组(hot Slot group)的 ISR/复制滞后超出阈值(默认 64 条 entry)持续 30 秒 → 失败;
- Leader 不均衡超过 20% 并持续 10 分钟→ 失败(
ObserverCodeLeaderImbalance)。
observer 的每个样本ObserverSample是"同一轮次的三节点投影",只包含低基数事实(healthy、cluster healthy、leader imbalance、lag breaches 计数),不携带任何原始响应、身份或凭据。
四、Task 2:固定组目录准备与 Worker 分配
4.1 组目录准备的幂等性
setup.go 通过GroupSetup使用现有 benchmark 准备 API 创建2,000 个确定性组频道(formalGroupCatalogTotal)与固定成员关系。三大约束:
- 幂等:同一
run_id重复执行是安全的,已完成的 run 直接返回成功; - 形状不匹配即失败:已 fence 的 run 若目录指纹(
groupSetupFingerprint,对 ID/成员/归属的派生标签做 SHA-256)不同,返回ErrGroupSetupShapeMismatch,且发生在任何目标变更之前; - person 频道绝不通过 setup API 预创建:setup 只写组目录(
groupChannelType = 2),人员频道只能由后续真实流量自然创建,这为 Task 3 的 meta-create 记账保留了语义纯净性。
组目录由 groups.go 的GroupCatalog描述:wkg-前缀组 ID、小/中/大/超大四档(超大群固定 100,000 成员、固定成员关系、每分钟一次超大群发送),单批次订阅者上限MaxGroupSetupSubscribersPerBatch = 1,000,以贴合下游订阅者 Raft 命令的固定 UID 数边界。
4.2 确定性分配与 fencing
计划要求把全局用户索引与速率权重确定性地切分为恰好三份,无重叠、无间隙,且单一 coordinator generation。实现中:
BuildCoordinatorAssignments(cfg, generation)生成CoordinatorAssignment(含WorkerFence:run_id、generation、worker 分段);- 快照聚合器
CoordinatorSnapshotAggregator拒绝合并来自其他run_id、其他 assignment 或其他 generation 的快照; NewCoordinator硬性要求恰好三个独立 worker(len(options.Workers) != coordinatorWorkerCount直接返回ErrCoordinatorConfig),Coordinator 一次生命周期只能使用一次(used标记),防止 generation 复用。
4.3 全局速率授予(Grant)
Coordinator 在正式流量开始前先下发初始 grant,随后以1 秒 cadence持续授予(coordinatorGrantCadence)。授予校验极其严格:
- 三个 worker 的速率之和必须等于 Phase 2 的全局 token bucket;
- grant tick 时间戳容忍平台定时器量化(10 ms),但拒绝延迟、跳过或追赶的 grant tick(
CoordinatorGrantFailureTick); - grant 投递容忍 250 ms 的运行时间抖动(
coordinatorGrantDeliveryTolerance),超过即视为 delivery 失败; - 快照聚合要求 histogram bucket schema 兼容;计数器回退、worker 时钟/序号过期、快照数不等于 3、fence 不匹配、聚合溢出分别对应
ErrCoordinatorSnapshotRegression/ErrCoordinatorSnapshotStale/ErrCoordinatorSnapshotCount/ErrCoordinatorSnapshotFence/ErrCoordinatorSnapshotOverflow。
任何 worker 在分配后失败,Coordinator 会停止其余 worker 并返回harness_invalid;任何服务进程连续 30 秒不可用,则停止 worker 并返回product_failure。两种运行都不会被恢复(no resume)。
五、Task 3:证明 loaded / 自然缺失 / reheat 的 Channel 生命周期
这是第四阶段最有技术含量的一步:用真实的、非注入式的方式证明产品在"Channel 冷却后能自然回收、收到消息后能无缝重载"。
5.1 有界 lifecycle-candidate lease
lifecycle_proof.go 定义LifecycleCandidate:一条瞬时、有界的证明租约,包含规范 person 频道身份、物理 Slot 分配(HashSlot/SlotID)、初始序号(InitialSequence)、静默窗口界限(QuietNotBefore/QuietDeadline)与确定性 reheat 截止(ReheatAt)。关键设计:candidate 是瞬时的,绝不原样进入快照或报告(ChannelID被刻意排除在所有聚合证据类型之外)。
5.2 每十分钟的均衡队列选择
计划要求每 10 分钟选出恰好1,200 个候选 = 12 个逻辑 Slot 组 × 100(实现常量lifecycleCohortSize = 1_200、lifecyclePerSlot = 100)。选择偏好:
- 优先选择已观察 loaded的 revisit 计划;
- 这些频道接下来超过产品自然的 5 分钟 idle eviction 间隔不会收到消息(
lifecycleNaturalQuiet = 5 * time.Minute); - 随后确定性 reheat。
重复频道或某个 Slot 队列供应不足 →harness_invalid。
5.3 全节点三态转换状态机
每个候选必须完整经历以下状态机(fake 显式探针响应驱动):
loaded on all three replicas with one leader and monotonic LEO/HW -> naturally absent from all three nodes without eviction API calls -> real SEND reheat -> loaded on all three replicas with sequence continuing above initial sequence任何以下情况都会使整个 lifecycle 队列失败,并以闭合的LifecycleProductFailureReason词汇归类:error、closing、卡在 loaded 超过有界静默截止、部分副本 reheat(partial reheat)、序号重置(sequence reset)、意外重载等(完整 11 类原因见LifecycleProductFailureCounters)。
特别值得注意的延迟分类规则:cold/reheat SENDACK 延迟只有在同一候选已在三个节点上证明 absent 之后才进入 cold 直方图;未能证明缺失的回归会话不进入 cold 直方图,避免"预热会话"污染冷启动延迟数据。
5.4 异步探针轮询
- 显式探针按批发出,每批 ≤ 1,200 个身份(
lifecycleMaxProbeBatch),并行度上限 32(lifecycleMaxProbeParallel),轮询全部三个服务节点; - 探针流量不得计入 Channel 活动,不得延长 eviction;
- 探针延迟与传输错误单独记账,不归入产品生命周期失败(避免探测开销污染判定)。
5.5 权威元数据创建计数对账
在每次 checkpoint,实现会计算"确定性 person edges + 已准备组目录"对应的期望唯一频道创建数,并与三节点wukongim_channelv2_meta_created_total{result="created"}之和核对:
- reheated 候选对期望唯一创建数的贡献为 0(重载不得重建元数据);
- 并发竞争失败者(concurrent losers)可以增加
already_existing,但不得增加created。
这一对账用聚合计数证明了"reheat 没有重建元数据",且无需引入 channel-ID 维度的指标标签。
六、Task 4:正确性、延迟、资源与集群阈值判定
判定体系集中在 verdict.go,由VerdictEvaluator将"有界滚动证据"归约为一个冻结结果。
6.1 正确性判定
任何已证实的消息丢失、重复、损坏或序号回退立即失败。TerminalSends与 Channel 激活拒绝必须为零(默认阈值即 0)。失败率采用精确有理数比较(rationalViolates用 128 位乘法避免浮点舍入):
- 整体运行首试失败率:默认
< 1/10,000(OverallFirstAttemptFailure,运算符<); - 每个一分钟窗口首试失败率:默认
≤ 1/1,000(AnyMinuteFirstAttemptFailure,运算符<=)。
worker 队列饱和或 observer 轮询间隙计数 > 0 →harness_invalid(VerdictCauseQueueSaturation/VerdictCauseObserverGap)。
6.2 延迟窗口判定
前两小时 warmup 之后,按五分钟滚动窗口(SustainedBreachWindow = 5 * time.Minute)执行三档延迟上限:
| 操作类 | p99 | p99.9 |
|---|---|---|
| Hot SENDACK | 400 ms | 1 s |
| Cold/reheat SENDACK | 2 s | 5 s |
| 全量会话同步 | 1 s | 3 s |
- 任一操作超过10 秒记为 anomaly 样本(
SingleAnomaly); - 阈值破坏持续满 5 分钟即失败;更短的破坏只记录为 warning/evidence,不改变判定。
实现细节上,VerdictEvaluator用CounterWindow做五分钟窗口内的AboveP99/Count有理比聚合,并在 warmup 边界保留"第一个跨越边界的累积 cut 只作基线、不进入实测证据"的语义,保证预热期延迟不会污染实测数据。同时,延迟破坏还支持归因(attribution):若破坏由基础设施饱和引起,最终判定降级为passed_with_capacity_warning而非产品失败;归因证据不足则判insufficient_evidence。
6.3 资源斜率判定
- 从每小时forced-GC 指标样本出发,计算滚动 6 小时 live-heap 斜率,超过 5% 失败;
- 计算24 小时 goroutine 斜率,超过 5% 失败;
- 队列深度/inflight 在突发后必须回到已建立的 warm baseline(burst ended 时若未回落则
VerdictCauseQueueRecovery失败); - 每个节点独立评估(三个
verdictResourceNode槽位),不允许用平均值掩盖某个泄漏节点; - 资源样本的 forced-GC 时间必须小时对齐,且拒绝 NaN/Inf/负数/小数 gauge 值。
6.4 闭合分类与优先级
最终判定采用闭合结果集(实现版比计划多出rehearsal_pass、passed_with_capacity_warning、insufficient_evidence三档):
pass / rehearsal_pass / passed_with_capacity_warning product_failure / insufficient_evidence harness_invalid / infrastructure_failure / operator_stop分类优先级规则与计划完全一致:磁盘低于 5% →infrastructure_failure;服务崩溃或产品阈值 →product_failure;worker/coordinator/observer 饱和 →harness_invalid。第一个 terminal cause 被冻结后不可更改,后续 cleanup 错误(worker stop / snapshot / observer)以独立的RecordCleanupError环形缓冲附加,不影响主判定。
6.5 有界滚动 reducer
window.go 提供两类内存有界的滚动窗口:
CounterWindow:保留固定容量内的精确有理数增量(一分钟失败率窗口容量 16、五分钟延迟窗口 64 样本),已过期条目可被覆盖,未过期条目绝不覆盖;GaugeWindow:保留最新样本与精确跨度前驱,用于 6 小时/24 小时斜率端点计算。
这保证了 72 小时长运行不会无限保留原始样本。
七、Task 5:连续 Checkpoint 与脱敏报告
7.1 连续运行的 checkpoint 语义
计划强调:两小时 shakeout 是独立的 run profile(实现RehearsalConfig,证据主张为rehearsal);正式运行中,24 小时 checkpoint 必须原子写入且不停止/不重分配 worker,同一进程与同一 run generation 继续跑向 72 小时最终判定。实现中CheckpointRecorder.CaptureAndWrite只消费快照与证据,没有任何 worker 生命周期或流量控制能力,输出失败可对同一快照 cut 重试。
7.2 版本化的 JSON / Markdown 输出
report.go 定义的Report契约包含:配置摘要(ConfigDigest)、数据集摘要(DatasetDigest)、拓扑证明、worker generations、时间窗口(start/warmup_end/qualification_at/final_at/end/elapsed)、消息/同步/生命周期/meta-create 记账、延迟/资源/集群证据、terminal 分类与容量结果。所有样本只保留稳定 index + SHA-256 hash(ReportSample{Class, Index, Hash})。三个契约常量被硬编码进每次输出:
ReportSchemaVersion = "wukongim/chat-lifecycle-report/v5";ReportThresholdVersion = "wukongim/chat-lifecycle-thresholds/v1"(报告绑定精确阈值语义,默认值演进后结果仍可解释);ReportDesignProfile = "chat-lifecycle-soak/2026-08-04"。
7.3 脱敏与原子写入
- Redaction 测试:用 bearer token、raw UID、具体 channel ID、标记 payload 播种 fixtures,序列化 JSON 与 Markdown 后断言全部不出现;
- 原子写入:
WriteReportAtomic在目标同目录创建0600权限的临时兄弟文件 → 写入 →fsync→close→rename→ 打开目录句柄再Sync一次。两步 fsync 保证断电/崩溃后不会出现半截报告。
报告写入器绝不把 warning-only 证据变成 pass/fail 变更(ReportWarningCode词汇表与判定解耦),并始终携带精确的 threshold version 与 design profile。
八、Task 6:老化数据容量阶梯
8.1 容量模式准入
capacity.go 规定:容量模式要求已完成 72 小时 checkpoint,且当前服务数据集必须与冻结 checkpoint 一致。实现通过CoordinatorCapacityDatasetProbe在 preflight 之后、任何 setup/worker 变更之前,从每个服务节点直接读取DatasetDigest(包含服务进程 generation,因此重启无法复用冻结的 checkpoint 身份),与CapacityAdmission中的Report比对,不匹配即ErrCapacityAdmission。
8.2 阶梯状态机
- 起点:2,000 SEND/s(
StartRatePerSecond); - 每步+25%(
StepPercent),持续30 分钟= 10 分钟稳定(Stabilize)+ 20 分钟测量(Measure); - 首个失败步之后,以10% 增量(
RefinePercent)细化边界区间; - 阶梯最多 192 步,快照只保留最近 32 步(
maxCapacityRecentSteps); - 整体搜索时长上限 8 小时(
MaximumDuration)。
CapacityPhase完整枚举:stabilize → measure → rate_pending → recovery → complete → terminal。每步的失败面用CapacityGateFailure位集记录:error rate、latency、queue/inflight、cluster lag、resource、readiness、lifecycle。
8.3 恢复与终局规则
- 失败/细化边界确定后,降到2,000 SEND/s 恢复 30 分钟,不重启任何服务节点;只有队列/inflight、延迟、错误率、集群 lag、资源压力全部回到接受的 baseline 范围,恢复才算通过;
- 产品正确性失败仍然立即终止(不受阶梯控制);
- 容量阈值失败只记录边界并进入有界细化/恢复序列;
- clean-dataset 容量是可选独立调用,绝不替代老化数据证据(
CapacityDatasetClean与CapacityDatasetLiveAged语义分离)。
容量阶梯的快照通过CoordinatorCapacityPeriodicHooks以与 soak 相同的周期性证据 cut 接入报告,最终以ReportCapacityEvidence(attempted/completed/attribution/lower_bound/maximum_passing_rate/first_failing_rate/recovery_passed)落入报告。
九、Task 7:阶段验证
计划收尾要求三类验证,均可直接在当前仓库复现:
# 1. 竞态检测下运行整个包 GOWORK=off go test -race ./internal/bench/chatlifecycle ./internal/bench/target -count=1 # 2. 重复确定性测试:count=20,fixtures 必须逐字节一致 GOWORK=off go test ./internal/bench/chatlifecycle -run 'RelationshipGraph|Assignment|LifecycleProof|Verdict|Capacity' -count=20 # 3. 检查阶段差异:无空白错误、无无关文件被暂存 git diff --check git status --short十、测试命令速查表
计划内六个任务的测试命令汇总如下(均已落地于internal/bench/chatlifecycle):
| 阶段 | 命令 |
|---|---|
| Task 1 观测/preflight | GOWORK=off go test ./internal/bench/target ./internal/bench/chatlifecycle -run 'Observer|Preflight|Disk|ClusterHealth' -count=1 |
| Task 2 组目录/分配 | GOWORK=off go test ./internal/bench/chatlifecycle -run 'Setup|Assignment|CoordinatorStart|Grant' -count=1 |
| Task 3 生命周期证明 | GOWORK=off go test ./internal/bench/chatlifecycle -run 'LifecycleCandidate|LifecycleProof|MetaCreateAccounting' -count=1 |
| Task 4 判定阈值 | GOWORK=off go test ./internal/bench/chatlifecycle -run 'Verdict|LatencyWindow|ResourceSlope|Classification' -count=1 |
| Task 5 checkpoint/报告 | GOWORK=off go test ./internal/bench/chatlifecycle -run 'Checkpoint|Report|Redact' -count=1 |
| Task 6 容量阶梯 | GOWORK=off go test ./internal/bench/chatlifecycle -run 'Capacity|Staircase|Recovery' -count=1 |
十一、总结:从计划到实现的关键设计原则
对照计划文档与internal/bench/chatlifecycle/实现,可以提炼出四条贯穿始终的设计原则,也是阅读本项目后续阶段(第五阶段容量搜索等)的钥匙:
- 身份与证据彻底分离:一切原始身份(UID、channel ID、token、payload)只存在于瞬态探针中;所有持久化证据要么是闭合词汇(cause/code/outcome),要么是 hash/index。这让 72 小时长跑产出的报告天然可归档、可审计、可公开。
- 判定即代码,而不是日志:pass/fail 由
VerdictEvaluator与Coordinator的闭合状态机冻结,第一个 terminal cause 不可变,后续 cleanup 错误独立记账——判定具有可复现性与确定性。 - 一切有界:候选队列、探针批次、滚动窗口、报告 warning/anomaly 数量、容量阶梯步数全部有界,长运行内存恒定。
- 真实流量驱动证明:Channel 冷却与重载证明不使用任何 eviction API 注入,而是等待产品自然的 5 分钟 idle eviction 后由真实 SEND reheat,再用 meta-create 计数对账证明"重载未重建元数据"——这是对产品行为最严格的黑盒验证。
如需深入某个子系统的源码细节,建议按以下顺序阅读:先 types.go 与 defaults.go 建立配置心智模型,再依次读 preflight.go、coordinator.go、lifecycle_proof.go、verdict.go,最后以 checkpoint.go 与 report.go 收尾,配合各*_test.go理解每个闭合词汇的判定边界。
- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
相关推荐
WuKongIM 聊天生命周期 Soak 压测第三阶段:Worker 运行时实现全解析
WuKongIM 聊天生命周期 Soak 压测第三阶段:Worker 运行时实现全解析 导读 本文基于 WuKongIM 仓库中的实施计划文档 2026 08
即时通讯后端深入解析 Angular 组件生命周期钩子:执行顺序、渲染回调四阶段与源码实现
深入解析 Angular 组件生命周期钩子:执行顺序、渲染回调四阶段与源码实现 本文基于 Angular 官方文档 组件生命周期指南 https://link.
前端Web框架openjiuwen.agent_evolving.experience:Agent 经验在线生命周期编排体系深度解析
openjiuwen.agent_evolving.experience:Agent 经验在线生命周期编排体系深度解析 经验(Experience)是 Agen
人工智能AI AgentAgent 框架大模型工具调用RAG提示工程强化学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考