在 HAOVP 的高可用设计中,我把服务发现、流量控制、熔断降级、数据复制、缓存、对象存储和监控放进同一套能力框架。要让它成为可验证的部署方案,还需要把每项主张转换成明确的部署对象、故障操作、观测指标和判定标准。
目前 HAOVP 已经有单机 Compose、1Panel 和多节点 Compose 文档,也完成了一轮接口与外部入口验收。但这些材料主要证明系统能够部署、启动和处理指定用例,不能直接证明节点故障时会自动恢复。
先把设计主张写成可测试句子
“系统具备高可用”无法直接测试。我会把它拆成更小的句子:
停止一个业务实例后,其他实例仍能处理指定请求
停止一个注册中心节点后,服务发现仍能工作
Redis 主节点不可用后,客户端能重新连接可写节点
MySQL 主库不可用后,能明确完成选主和流量迁移
对象存储主写入点不可用后,能够从副本恢复指定对象
消息组件不可用时,核心业务按约定降级每句话都要有前置条件、操作步骤和可观察结果。如果一句话无法设计验证方法,它通常还只是架构口号。
建立设计、实现和验证映射表
我会为每个高可用方向建立一张映射表:
| 能力方向 | 方案设计 | 仓库实现 | 当前验证 | 仍缺什么 |
|---|---|---|---|---|
| 服务发现 | 多节点注册中心 | Nacos 配置与多节点编排 | 正常环境下服务可发现 | 节点停止与网络分区结果 |
| 流量保护 | 限流、熔断、降级 | Sentinel 依赖与配置方向 | 接口功能验收 | 受控流量与恢复探测 |
| 数据库 | 主从与恢复 | 一个主库、多个从库配置 | 复制方案文档 | 自动选主、隔离与入口迁移 |
| Redis | 主从与 Sentinel | Sentinel 配置与连接方式 | 正常状态检查方法 | 实际切换时间与状态完整性 |
| 对象存储 | 多副本 | 主写入点与单向镜像脚本 | 对象存储功能链路 | 同步调度、接管和回切 |
| 消息链 | 异步解耦与降级 | RocketMQ 与主表降级更新 | 指定接口核心结果符合预期 | 路由恢复、幂等、重放与对账 |
这张表的作用不是让所有格子都填成“完成”,而是防止设计目标和仓库现状被写在同一层。
单机接口通过不能替代多节点验证
4 月 18 日的三批后端接口验收共有 115 个预设用例,均符合预期;外部统一入口另有 29 个用例符合预期。
这可以支持:
- 正常环境下主要接口链路可运行;
- 入口、认证和业务路由能处理指定请求;
- 正向和负向用例的结果符合预期;
- 一些运行版本、权限、事务和映射问题已经修复。
它不能支持:
- 任意服务实例停止后请求无损迁移;
- MySQL 或 Redis 自动切换;
- Nacos 网络分区恢复;
- MinIO 副本自动接管;
- 消息积压恢复后不丢不重;
- 高并发和长期稳定性。
两组验收也可能覆盖相同链路,不能相加为 144 个独立接口。
为故障测试建立正常基线
在注入故障前,先建立可重复的正常状态:
固定代码和镜像版本
固定配置版本
准备脱敏测试数据
启动持续请求
记录正常成功率与延迟
记录服务、数据库和中间件状态如果正常基线本身不稳定,故障后的变化无法归因。
基线还要确认运行产物与源码一致。4 月验收曾发现旧 JAR 问题,因此每次测试前都需要记录源码、JAR、镜像和容器版本。
业务服务实例怎样验证
服务多实例的测试可以从一个明确接口开始:
持续请求统一入口
-> 确认请求落到多个实例
-> 停止其中一个实例
-> 记录失败请求和发现时间
-> 观察流量是否只到健康实例
-> 恢复实例并检查重新注册需要记录:
- 故障前后实例列表;
- 请求失败类型和数量;
- 服务发现剔除与恢复时间;
- 是否有本地会话或临时文件丢失;
- 重试是否造成重复写入。
只停止进程后看到另一个容器仍是绿色,不能证明业务请求已经完成切换。
Nacos 节点怎样验证
注册中心测试要区分:
单节点进程停止
节点间网络中断
共享数据库异常
客户端与集群之间网络中断观测内容包括:
- 集群成员和健康状态;
- 已注册实例是否仍可查询;
- 新实例能否注册;
- 配置能否读取和更新;
- 已运行服务是否继续使用本地缓存信息;
- 网络恢复后是否自动追平。
不同故障的表现不一样,不能用一次停止容器覆盖所有 Nacos 高可用结论。
Sentinel 规则怎样验证
规则存在只是准备。验证至少需要:
正常基线
-> 逐步增加受控流量或制造慢调用
-> 观察限流或熔断触发
-> 检查返回与日志
-> 确认下游资源得到保护
-> 恢复依赖
-> 观察半开和恢复阈值需要结合接口耗时、实例数量、连接池和数据库容量确定。没有这些信息时,只能使用初始实验值,不能写成系统承载能力。
Redis Sentinel 怎样验证
Redis 测试不能停在“新主节点出现”。完整流程需要:
- 持续执行可判定的读写;
- 停止当前主节点;
- 记录 Sentinel 发现与选主过程;
- 观察应用连接失败与恢复;
- 核对切换前最后写入是否存在;
- 恢复旧节点并确认它不再接受错误写入;
- 检查验证码、令牌或权限状态的业务影响。
要区分缓存可丢数据和认证状态。某些缓存可以从数据库重建,令牌和临时状态丢失则可能直接影响用户会话。
MySQL 主从怎样验证
当前多节点方案确认了主从复制和主库写入方向,但真正的故障切换还需要:
检测主库故障
-> 隔离旧主库
-> 比较从库进度
-> 提升新主库
-> 让其他从库改换来源
-> 迁移应用入口
-> 恢复连接
-> 核对事务与数据测试要记录人工操作和自动操作分别有哪些。若需要人工修改连接地址,就不能写成自动切换。
还要测试“提交结果不确定”的事务:应用发送提交后连接中断,客户端可能不知道事务是否生效。盲目重试可能产生重复业务数据。
对象存储怎样验证
当前 MinIO 方案是主写入点到一个副本的单向镜像,不是原生纠删码集群。
验证需要覆盖:
- 新对象何时出现在副本;
- 覆盖、删除和失败重试的语义;
- 对象大小或校验值是否一致;
- 主写入点停止后怎样修改入口;
- 副本是否允许继续写入;
- 主节点恢复后怎样处理两端差异。
同步脚本存在不能证明同步已经持续运行,更不能证明副本会自动接管。
消息降级怎样验证
RocketMQ 路由异常时,内容服务可以直接更新主表核心计数。但正常消费者还会更新每日统计,降级路径不一定覆盖这部分。
因此需要分别验证:
正常发送与消费
生产者发送失败并降级
消息已入 Broker 但响应不确定
消费者处理失败与重试
组件恢复后的积压处理
主表与每日统计对账如果消息已经进入 Broker,同时生产者又执行主表降级,后续消费可能重复加一。事件唯一编号和幂等消费是需要继续补充的能力,不能只看接口返回成功。
监控要服务于判定
Prometheus 和 Grafana 不能只是展示 CPU 和内存。每个故障场景都应提前定义需要观察的指标:
- 请求量、错误率和高分位延迟;
- 实例健康、注册数量和连接状态;
- 数据库连接、锁等待和复制延迟;
- Redis 主节点与 Sentinel 状态;
- 消息发送失败、消费延迟和积压;
- 对象同步成功、失败和差异;
- 容器重启、磁盘与网络状态。
指标还要与日志和请求标识关联。否则测试中看到异常,也很难定位发生在哪一层。
结果记录要能支持或否定主张
每个场景使用统一结构:
测试主张
环境与版本
前置条件
故障操作
持续业务流量
观测指标
实际结果
恢复操作
数据核对
是否支持主张
未覆盖范围“是否支持主张”可以是通过、部分通过或不支持,而不是只能写通过。
例如:
主张:停止一个业务实例后核心查询仍可用
结果:查询恢复,但切换期间出现失败请求
结论:部分支持,需要记录失败窗口并继续优化这是通用结果格式,不是 HAOVP 已经执行的故障结果。
当前可以进入哪一步
到 6 月 6 日,高可用设计、仓库编排和接口验收已经为故障验证提供了对象与基线。下一步不是继续增加组件,而是为现有组件逐项建立可重复故障场景。
我会把每句高可用结论放回“设计—实现—验证”映射表:只有在明确环境中执行过故障操作、记录过请求和数据结果的部分,才升级为已验证能力;其余内容继续保留为设计方向或仓库实现。
高可用部署方案的价值,不在于图里有多少节点,而在于故障发生时能否预测系统行为、观察变化、恢复服务并核对数据。设计提供问题框架,部署文件提供实验对象,验证记录才决定最后可以写出多强的结论。