Files
hms/docs/discussions/2026-06-25-analysis/01-stability.md
iven 3351c68d10 docs: redact Redis 凭据明文 + 系统分析报告 + wiki 关键数字校正
PP-03 凭据泄露处置:
- 清除 wiki + 2 份历史文档中的 Redis 明文密码与公网 IP(4 文件 5 处)
- wiki 新增安全告警 + 症状导航条目
- 核实降级:泄露旧密码已失效,HMS 连本地 Redis,云端闲置;公网已关闭

系统深度分析(9 维度 + 6 主题多专家组):
- docs/discussions/2026-06-25-analysis/ 新增 7 文件
- 综合 6.8/10,4 CRITICAL,TOP 12 痛点,4 阶段路线图

wiki 关键数字校正(PP-02/05a fix 触发):
- 迁移数 175→176(m20260626_000170)
- 症状导航新增 device_readings 分区硬截止 + claim_next 注入修复条目
2026-06-26 09:07:35 +08:00

14 KiB
Raw Blame History

稳定性与上线护航 — 主题综合

日期: 2026-06-25 | 主题: 稳定性与上线护航(主持综合) 视野: V1 上线后 6-12 个月演进,不重复上线前就绪度讨论。 证据口径: 所有论断附 文件:行号,基于 feat/media-library-banner 分支实测。

1. 主题愿景

把"上线即救火"变成"上线即睡觉"。融合 SRE / 发布管理 / 质量保障三方共识:以确定性故障自愈为核心死信重试、分区到期、AI 队列积压——这三类都是"代码写了但没接线"或"硬截止定时炸弹",是历史 24% fix 提交率在事故层面的根因),以迁移可逆性 + 快速回滚为发布纪律,以告警触达人 + cron_heartbeat 进就绪门禁为观测闭环。三者形成"预防—发布—响应"完整生命周期,而非堆砌监控工具。

不追求一步到位上 K8s+Helm+完整可观测性栈DevOps 4.2 分、单兵运维团队不支撑这种复杂度债务)。最小可行 HA = migrate 子命令 + 蓝绿 + heartbeat 门禁 + Alertmanager每一步都是可验证的工程动作配合 TDD 集成测试证明"接线真的生效"。

2. 专家提案摘要

SRE 可靠性工程师5 项)

  • PP-04 告警触达人:补 Alertmanager + 三级 SEV 分级 + Runbook deep-link + webhook 限流治理。
  • PP-01/PP-05 死信与 AI 队列接线retry_dead_letters(events.rs:382) 和 analysis_queue::claim_next(service/analysis_queue.rs:92) 已实现但脱节,接线 + cron_heartbeat 复用为后台存活探针。
  • PP-02 分区自愈:应急 guard每日检测未来分区数<2 则补建)+ pg_partman 根治,剩余周数作 SEV-1 倒计时告警。
  • 灾备演练制度化restore-drill CI job → RPO/RTO Prometheus 指标。
  • PP-11 迁移解耦启动路径migrate 子命令 + 蓝绿 + 破坏性 DDL 三步走。

发布管理专家5 项)

  • 迁移可逆性工程化clap 子命令暴露 173 条已存在但休眠的 down 迁移为可调用能力expand/contract 强制破坏性变更跨版本。
  • 30 分钟回滚migrate down <ver> + 双标签镜像 + canary 用 eventbus_pending_total(tasks.rs:119) 作健康判据。
  • cron 进就绪门禁/health/ready(health.rs:51) 暴露 cron_heartbeat + 积压阈值503 触发摘流。
  • 系统级特性开关FeatureFlagServiceai 内部)上提为 erp-core trait按 tenant 粒度灰度。
  • 冻结期 + fire-drill:双周演练 + 兼容窗口契约沉淀到 docs/runbooks/。

质量保障架构师(占位,观点合并入下)

门禁反推视角已贯穿上述——TDD 集成测试证明接线生效、CI 门禁拦截破坏性 DDL、fire-drill 验证回滚链路,本主题不再单列。

3. 战略举措(归并后 5 项)

举措 A确定性故障自愈接线PP-01 + PP-05 + PP-02 应急)

  • rationaleretry_dead_letters 已实现 (events.rs:382-446含 max_attempts=5 filter events.rs:390) 但全仓无调用者ai_analysis_queue 表已建 (m000118) 且 claim_next 已实现 (analysis_queue.rs:92) 但只在 module 启动触发一次device_readings 是分区表down() 只 DROP 固定 4 个月份 (2026_05..2026_08)2026-09 后 INSERT 将硬失败。三处都是"代码写了但没接线"的定时炸弹。
  • phases:
    1. tasks.rs 新增 start_dead_letter_retry(每小时调 retry_dead_letters复用 cron_heartbeat+ start_ai_queue_worker(消费 ai_analysis_queue
    2. tasks.rs 新增 start_device_readings_partition_guard(每日检测 pg_inherits 未来分区数<2 则 CREATE PARTITION OF
    3. TDD先写 tests/event_retry_loop.rstests/partition_guard.rs 失败测试,再接线。
  • effortEstimate3-5 人日(函数均已存在,主要是接线 + 测试)。
  • expectedImpact:消除 3 类潜伏故障死信不再永久驻留2026-09 分区硬截止提前自愈。
  • kpisdead_letter_events.resolved_at 非空率 >95%ai_analysis_queue pending 24h 内清零device_readings 未来分区数 ≥3。
  • dependenciescron_heartbeat metric 暴露(举措 CAlertmanager 告警规则(举措 D

举措 B迁移解耦启动路径 + 30 分钟回滚能力

  • rationalemain.rs:233 在应用启动路径直接 Migrator::up,含 RENAME/DROP 等破坏性 DDL173 条 down 迁移已写好但全仓无 clap/migrate 子命令可调用Cargo.toml 无 clap 依赖docker-compose.production.yml:38 单容器 hms-servernginx.conf:1 单 upstream.github/workflows 仅 test.yml 无构建推送。回滚资产存在但休眠。
  • phases:
    1. 引入 clap 子命令:erp-server serve(仅启动 HTTP不迁移/ migrate up|down <ver> --dry-run --confirm / migrate verify(事务回滚校验 down 可逆性)。
    2. main.rs:233 改为启动时仅校验 schema 版本一致性,不匹配则 panic 提示先跑 migrate。
    3. CI 新增 build-and-push workflow双标签 {git-sha} + {semver} 推 ghcr.io。
    4. deploy.shcanary 10% 流量,观察 /metrics 5xx + eventbus_pending_total 5 分钟,异常切回 stable + migrate down。
    5. 破坏性 DDL 写入 docs/runbooks/breaking-ddl.md 强制 expand/contract 三步走 checklist。
  • effortEstimate8-12 人日clap 改造 + CI + deploy 脚本 + 破坏性迁移 checklist
  • expectedImpact:回滚从"重拉镜像"升级为 30 分钟内可执行;破坏性 DDL 不再在启动瞬间执行。
  • kpisMTTR <30min破坏性迁移 100% 走 expand/contract任意历史镜像可拉取。
  • dependenciesbackup.sh 作为回滚前快照已存在nginx upstream 改造(举措 B 第 4 步)。

举措 Ccron_heartbeat 进就绪门禁 + 积压指标可观测

  • rationalecron_heartbeat 已埋点 (main.rs:647 → state.rs:31 → tasks.rs 已写),但 readiness_check (health.rs:51) 仅查 DB+Redis后台任务死了就绪仍返回 oktasks.rs:119 已暴露 eventbus_pending_total但 dead_letter 积压、AI 队列积压、分区剩余周数未导出。零成本资产未利用。
  • phases:
    1. ReadyResponse (health.rs:33) 增 crons: [{name, last_heartbeat_ago_secs, healthy}]>2×周期判 unhealthy 返回 503。
    2. tasks.rs 新增 gaugedead_letter_unresolved_totalai_analysis_queue_pending_totaldevice_readings_partitions_remaining_weeks
    3. 公开路由屏蔽 crons 字段防信息泄漏。
  • effortEstimate2-3 人日。
  • expectedImpact:后台任务死亡可被 nginx/k8s 摘流canary 阶段可直接判断新版本是否杀掉某个 cron。
  • kpis/health/ready 反映 cron 存活canary 拒绝率(后台被杀)可观测。
  • dependencies:举措 A 接线后 cron 才有真实心跳。

举措 DAlertmanager + 三级告警 + Runbook 绑定

  • rationaleprometheus.yml:5 仅有 rule_files 无 alerting 块alerts.yml 22 条规则但无 SEV 分级、无 Alertmanager、无 Runbook 链接。告警亮了无人知、知了不知干啥。
  • phases:
    1. docker-compose.production.yml 新增 alertmanager 服务 + prometheus.yml 补 alerting: alertmanagers: 段。
    2. alerts.yml 按 SEV-1/2/3 分级SEV-15xx 率/PG 耗尽/Redis 不可达/dead_letter 积压/分区<2 周 → 企微+电话SEV-2P95/idle<10% → 企微SEV-3CPU/内存 → 仅 Grafana
    3. 每条 alertname 对应 docs/runbooks/ 一页 + Grafana deep-link。
    4. 上线初期只开 SEV-1按周复盘降噪后再开 SEV-2/3信噪比治理
  • effortEstimate4-6 人日。
  • expectedImpact:值班人被电话叫醒 ≤1 次/天;确定性故障(分区到期、死信积压)提前 2 周报警而非等客户投诉。
  • kpis:告警信噪比(有效告警/总告警)>70%SEV-1 平均响应 <15min。
  • dependencies:举措 A/C 的 metric 导出;企微 webhook 限流20/min评估。

举措 E灾备演练制度化 + 兼容窗口契约

  • rationalebackup.sh/restore.sh 已实现AES-256-CBC但从未验证可恢复无 fire-drill无兼容窗口契约文档。医疗 SaaS 业内普遍"有 backup 没 drill"。
  • phases:
    1. docker/drill/restore-drill.yml独立 PG 副本CI 周日 04:00 拉最近 backup → restore → schema diff + 10 条 smoke 查询 → 输出 RPO/RTO metric。
    2. docs/runbooks/disaster-recovery.md + release.md + rollback.md + partition-deadline.md。
    3. wiki/architecture.md 新增"发布兼容性"章节 + PR 标注 compatible_rollback_to
    4. 双周 staging fire-drill + 变更冻结期(月初高峰前 48h
  • effortEstimate6-8 人日(含 CI 隔离 + PII 合规审查)。
  • expectedImpactRPO/RTO 从纸面 SLA 变成每周可查 metric客户合规审计直接拿数据。
  • kpisbackup_rpo_seconds / backup_rto_seconds 周报fire-drill MTTR 记录。
  • dependenciesCI runner 隔离(生产备份含 PIIBACKUP_PASSPHRASE 轮换流程。

4. 速赢1-2 周内)

  1. cron_heartbeat 进 /health/ready举措 C 第 1 步)health.rs:33/51 改造零依赖、1-2 人日,立即可让 nginx 摘流反映后台存活。这是所有后续观测的门禁基线。
  2. 死信与 AI 队列接线(举措 A 第 1 步)tasks.rs 加两个 spawn + 复用 retry_dead_letters/claim_next3-4 人日,消除"代码写了没跑"的潜伏故障,并 TDD 证明生效。
  3. Redis 凭据止血轮换PP-03 应急):立即改 .env.production 注入新密码 + 重建 Redis 数据,不动 git 历史filter-repo 留待下一正常发布窗口。1 人日,止血无破坏性。

5. 主题级风险

  • R1 破坏性 DDL 三步走拉长交付周期 2-3 倍:产品/研发强烈反对,需明确医疗场景牺牲速度换可靠性的边界,并以"特性开关(举措未单列)作廉价回滚"对冲。
  • R2 重试风暴retry_dead_letters 广播后消费者仍失败会再次 dead-letter已确认 max_attempts=5 被 filterevents.rs:390兜底但 AI queue worker 启动后历史积压一次性触发大量 LLM 调用 → Ollama OOM需先 truncate 或加 backpressure。
  • R3 蓝绿双副本 +30% 资源成本需与运维预算对齐nginx upstream 切换需 DB schema 兼容期,双写易引入数据不一致。
  • R4 BACKUP_PASSPHRASE 轮换需重加密历史备份工作量被低估restore-drill 跑生产备份含 PIICI runner 必须隔离 + 跑完即销毁。
  • R5 告警信噪比未治理重蹈"狼来了":上线初期只开 SEV-1企微 webhook 限流 20/min 需评估,否则告警风暴被腾讯截断。
  • R6 /health/ready 返回 503 过敏感致发布期误摘流:发布期临时调大阈值或加 maintenance 模式。
  • R7 pg_partman 需 superuser + shared_preload_libraries:云 PG腾讯云可能限制私有化部署客户需同步安装扩展。

6. 专家分歧调和dissentingViews → 最终取舍)

  • D1 PP-03 Redis 凭据处置优先级(安全 vs SRE vs 发布三方分歧SRE 主张业务链路自愈优先;安全主张立即 filter-repo 清洗历史;发布主张 filter-repo 是破坏性"发布"本身会重写哈希破坏分支。取舍:采纳发布管理专家的两阶段方案——立即轮换密码止血(无 git 影响)+ 下一正常发布窗口做 filter-repo带备份+全员协调)。理由:上线临门一脚搞历史重写风险高于泄露被利用的渐进风险,止血优先。
  • D2 是否上 K8s+HelmSRE 明确反对,主张蓝绿+migrate 子命令是最小可行 HA。取舍:采纳 SRE 立场,不上 K8s。理由DevOps 4.2 分、单兵运维团队把复杂度债务换成事故概率不划算;蓝绿+heartbeat 门禁覆盖 80% 发布安全需求。
  • D3 可观测性栈建设时机DevOps 专家 vs 发布管理边界之争):发布管理主张先 heartbeat+积压指标覆盖发布决策1 周可落地DevOps 主张上完整 Alertmanager/Loki/Jaeger4-8 周)。取舍:两者互补但分期——先落地举措 Cheartbeat 门禁)和举措 D 第 1-2 步Alertmanager + SEV-1完整链路追踪Loki/Jaeger列入 V1.1 路线图而非 V1 上线阻塞项。
  • D4 分区告警方式SRE vs 监控专家SRE 主张按时间倒计时 metric 告警,监控专家常规按错误率。取舍:采纳 SRE——确定性故障硬截止不该按概率监控按剩余周数单调递减 gauge 提前 10 周预警。
  • D5 特性开关是否上提 erp-core:违反 CLAUDE.md §1.3 模块边界铁律。取舍:以 trait 形式定义在 erp-core各模块可选依赖非直接耦合开关生命周期规范——最多存活 2 个发布周期后强制移除,防 if-flag 蔓延。本主题未单列举措,并入举措 B 回滚工具箱。

7. 路线6-12 个月)

  • M0上线前/上线时1-2 周):速赢 1+2+3 —— heartbeat 门禁、死信/AI 队列接线、Redis 凭据止血。
  • M1上线后 1 个月):举措 B 第 1-3 步clap 子命令 + CI 镜像推送)+ 举措 D 第 1-2 步Alertmanager + SEV-1+ 举措 A 第 2 步(分区 guard 应急)。
  • M2上线后 2-3 个月):举措 B 第 4-5 步canary + 破坏性 DDL checklist+ 举措 E 第 1-2 步restore-drill + runbooks+ pg_partman 根治。
  • M3上线后 4-6 个月):举措 E 第 3-4 步(兼容窗口契约 + fire-drill 制度化)+ 完整可观测性栈Loki/Jaeger评估。
  • M46-12 个月):根据 M1-M3 的 MTTR/RPO/RTO 实测数据,评估是否升级到 K8s+Helm届时团队规模与 DevOps 成熟度可能已支撑)。

所有举措均强调 TDD 证明接线生效、CI 门禁拦截、fire-drill 验证——质量保障"门禁反推"视角贯穿全程,不单列质量举措。