mirror of
https://gitee.com/lakernote/easy-next-admin.git
synced 2026-09-03 05:53:52 +08:00
Publish the current verified project state without local development history or personal-path artifacts.
15 KiB
15 KiB
稳定性体系蓝图
本文不是当前实现盘点,而是把 SRE 方法论、RFC、云厂商 Well-Architected 框架和主流可观测平台的稳定性实践,整理成一套适合中小型企业后台落地的稳定性体系。EasyNextAdmin 后续按本文做能力沉淀和缺口扫描。
一句话目标
稳定性不是“永不出故障”,而是让系统在故障、流量波动、依赖异常、发布变更和人为误操作下:
- 少出问题。
- 出问题能快速发现。
- 影响范围可控。
- 能快速恢复。
- 能通过复盘降低重复发生概率。
设计约束
中小型企业的稳定性方案要务实:
- 不追求超出业务价值的 99.999%。
- 不用复杂架构掩盖基础工程缺失。
- 不把所有问题都交给 Kubernetes 或云平台。
- 不依赖英雄式救火。
- 不让重试、队列和缓存把故障放大。
- 优先保护登录、权限、核心 CRUD、文件、任务、审批和审计链路。
标准和方法论
| 领域 | 标准或资料 | 核心启发 |
|---|---|---|
| SLO / 错误预算 | Google SRE: Implementing SLOs、Alerting on SLOs | 用用户可感知 SLI/SLO 和错误预算管理稳定性,而不是只看资源阈值。 |
| 错误预算策略 | Google SRE: Error Budget Policy | 错误预算耗尽时要有明确发布冻结、优先级调整和复盘策略。 |
| AWS Reliability | AWS Well-Architected Reliability Pillar | 可靠性覆盖设计、交付、运行、恢复和生命周期测试。 |
| Azure Reliability | Azure Well-Architected Reliability principles | 可靠性要贯穿开发生命周期,并用 checklist 驱动行动。 |
| Google Cloud Reliability | Google Cloud Architecture Framework: Reliability | 可靠性设计要覆盖部署、运行、恢复、容量和运营流程。 |
| 探针 | Kubernetes Liveness / Readiness / Startup Probes | liveness 决定是否重启,readiness 决定是否接流量,startup 保护冷启动。 |
| HTTP 幂等 | RFC 9110 | 自动重试必须尊重 HTTP 方法和业务幂等语义,非幂等请求不能盲目重试。 |
| 限流 | RFC 6585 | 限流应返回 429,并尽量给 Retry-After。 |
| 错误详情 | RFC 9457 | 跨系统 API 可用机器可读错误详情增强恢复和定位。 |
厂商打法
| 厂商或生态 | 稳定性打法 | 对中小企业的借鉴 |
|---|---|---|
| Google SRE | SLO、错误预算、burn rate 告警、复盘和减少 toil。 | 先用少量关键 SLO 管理稳定性,不要直接堆监控项。 |
| AWS Well-Architected | 多 AZ、自动恢复、容量规划、变更管理、备份恢复、演练。 | 把“恢复能力”和“演练”纳入稳定性,而不只看可用性。 |
| Azure Well-Architected | checklist、冗余、恢复目标、故障模式分析、运营流程。 | 用 checklist 固化架构评审,避免漏项。 |
| Google Cloud Architecture Framework | 可靠性、运营卓越、自动化、发布和监控联动。 | 把稳定性融入研发流程,发布前就定义观测和恢复方案。 |
| Datadog SLO | SLO 管理、标签检索、服务视图、错误预算告警。 | SLO 要能按服务、环境、团队检索和归属。 |
| New Relic Service Levels | 用 SLIs/SLOs 和 burn rate 连接用户体验和告警。 | 以“坏事件”消耗错误预算,而不是只看单点异常。 |
| Grafana SLO | SLI、目标、时间窗口、错误预算和告警规则集成。 | 开源栈也可以建立 SLO,不必依赖商业平台。 |
| Honeycomb SLO | burn alerts 从 SLO 直接跳到事件级调试。 | 告警必须能带人进入可排查上下文。 |
| 阿里云 / 腾讯云 / 华为云 | 云资源、应用、日志、链路、事件和告警统一平台化。 | 已上云团队优先复用云厂商能力,应用侧保持标准化,降低迁移成本。 |
厂商共性可以抽象为六层:
目标定义 -> 故障隔离 -> 自动恢复 -> 变更控制 -> 数据保护 -> 复盘改进
稳定性能力模型
| 层 | 解决的问题 | 典型能力 |
|---|---|---|
| 目标层 | 什么叫稳定,容忍多少失败 | SLI、SLO、错误预算、SLA 边界 |
| 入口层 | 如何保护入口不被打垮 | 限流、鉴权、请求大小限制、超时、排队上限 |
| 依赖层 | 下游慢或挂了怎么办 | 超时、重试、熔断、隔离、降级、缓存 |
| 并发层 | 资源耗尽怎么办 | 线程池、连接池、队列、背压、拒绝策略 |
| 数据层 | 重复、丢失、不一致怎么办 | 幂等、事务、Outbox、锁、补偿、审计 |
| 任务层 | 异步和定时任务是否可靠 | 调度日志、分布式锁、重试、死信、人工处理 |
| 变更层 | 发布如何不制造故障 | CI、迁移、灰度、回滚、配置审计 |
| 恢复层 | 出故障如何恢复 | 备份、恢复演练、RTO/RPO、runbook |
| 改进层 | 如何避免重复故障 | 复盘、行动项、故障注入、容量复盘 |
SLO 体系
SLO 要少而准。中小企业后台初期只建议定义 4-6 个。
推荐 SLI
| 用户旅程 | SLI | 坏事件示例 |
|---|---|---|
| 登录 | 登录请求成功率、p95 延迟 | 5xx、业务系统错误、超时 |
| 核心 API | /api/** 成功率、p95 延迟 |
5xx、系统异常、超时 |
| 权限和菜单 | 登录后获取菜单和权限成功率 | 权限快照失败、菜单加载失败 |
| 文件 | 上传、下载、预览成功率 | 上传失败、下载 5xx、存储不可用 |
| 任务调度 | 按计划执行成功率、调度延迟 | 任务失败、超时、连续失败 |
| Outbox | 消息最终成功率、最老失败年龄 | ERROR、超过重试窗口 |
推荐目标
初始目标不要过高:
- 内网后台核心 API:月度 99.5%。
- 登录链路:月度 99.9%。
- 核心 API p95:800ms 或根据实际压测调整。
- 任务执行:月度 99%,失败 10 分钟内可见。
- Outbox:ERROR 为 0,FAILED 10 分钟内重试或告警。
目标设置原则:
- 先用历史数据校准,没有历史数据就从保守目标开始。
- SLO 低于用户感知底线没有意义。
- SLO 高到长期没有错误预算也没有意义。
- 每个 SLO 必须有 owner、窗口、计算口径、排除项和响应策略。
错误预算和告警
错误预算 = 100% - SLO 目标。
使用方式:
- 预算健康:正常发布。
- 预算快速燃烧:暂停高风险变更,优先处理稳定性问题。
- 预算耗尽:冻结普通发布,只允许 P0/P1 故障修复和安全修复。
- 单次事故消耗大量预算:必须复盘。
告警分级:
| 等级 | 含义 | 示例 |
|---|---|---|
| Page | 现在必须处理 | 登录不可用、错误预算快速燃烧、数据库不可用、Outbox ERROR 堆积 |
| Ticket | 几天内处理 | 容量趋势逼近阈值、任务偶发失败、缓存命中率持续下降 |
| Log | 只记录上下文 | 单次重试成功、短暂抖动、无用户影响的自动恢复 |
推荐采用多窗口 burn rate:
- 短窗口发现快速故障。
- 长窗口避免噪声。
- 告警内容必须带 runbook、面板链接、最近发布、trace/log 查询入口。
韧性模式
Timeout
- 所有外部调用必须有连接超时和读取超时。
- 超时要小于用户请求总预算。
- 数据库、Redis、HTTP、对象存储、消息中间件都要单独配置。
Retry
- 默认只重试幂等读。
- 写请求只有在有幂等键、业务去重或确认原请求未生效时才重试。
- 使用指数退避和抖动。
- 遵守
Retry-After。 - 设置最大次数和总耗时上限。
Circuit Breaker
- 按下游服务和操作拆分。
- 失败率、慢调用率、半开探测要配置。
- 熔断时必须有降级响应或明确失败。
Bulkhead
- 关键业务和非关键业务隔离线程池或连接池。
- 慢下游不能占满全局业务线程池。
- 文件、报表、导入导出等重操作单独限制。
Rate Limit
- 登录、验证码、导入导出、文件上传、批量操作优先限流。
- 返回 429 和可计算的
Retry-After。 - 区分用户、IP、租户、全局维度。
Backpressure
- 队列必须有上限。
- 满了就快速失败或降级,不无限堆积。
- 客户端要能看到明确错误和重试建议。
Idempotency
- POST 写操作需要业务幂等键或服务端去重。
- 幂等结果要定义:重复请求返回原结果、拒绝还是提示处理中。
- 幂等记录要有过期时间和清理策略。
Outbox
- 本地事务和消息发送解耦。
- 失败重试使用退避。
- 达到最大重试进入人工处理。
- 监控 FAILED、ERROR、最老消息年龄和重试成功率。
Graceful Shutdown
- 停止接新流量。
- 等待进行中请求和任务完成。
- 超时后强制退出。
- 关闭前刷新日志和指标。
健康检查和探针
三类探针必须分开:
- liveness:进程是否需要重启。不要依赖数据库、Redis、下游服务。
- readiness:实例是否能接流量。要检查关键依赖和应用初始化状态。
- startup:启动慢时保护实例,避免冷启动被 liveness 误杀。
建议:
- 容器健康检查用 liveness。
- 负载均衡摘流用 readiness。
- 迁移、缓存预热、首次启动慢时加 startup。
- 可选依赖按功能开关决定是否进入 readiness。
发布稳定性
发布前:
- 自动化测试。
- 数据库迁移预演。
- 回滚方案。
- 指标和告警确认。
- 默认账号、CORS、Actuator、OpenAPI、安全头检查。
发布中:
- 记录发布事件。
- 观察登录成功率、API 错误率、p95、数据库连接池、Outbox、任务失败。
- 高风险变更灰度或低峰发布。
发布后:
- 看 SLO 是否异常燃烧。
- 看错误日志是否出现新异常类型。
- 看用户侧前端错误是否升高。
- 确认无异常后关闭变更窗口。
数据库迁移原则:
- 优先 expand / migrate / contract。
- 先兼容旧代码和新代码。
- 大表变更避免长锁。
- 不可逆迁移必须有备份和人工确认。
数据保护
中小企业也必须定义:
| 项 | 要求 |
|---|---|
| RTO | 多久恢复服务 |
| RPO | 最多丢多少数据 |
| 备份范围 | MySQL、Redis 持久化、上传文件、审计日志、配置 |
| 备份频率 | 全量、增量、binlog 或对象存储版本 |
| 恢复演练 | 至少季度演练核心数据恢复 |
| 校验 | 备份可用性校验,不只检查文件存在 |
容量和增长治理
稳定性不仅是服务不宕机,也包括数据增长不会把数据库、备份和查询拖垮。
- 高增长表必须有默认时间范围和清理策略,典型包括 API 访问日志、登录日志、错误日志、任务执行日志、消息重试表。
- 在线查询默认查热数据,历史数据走归档库、对象存储或离线检索,不要让后台页面无条件扫全表。
- 清理任务要限批、限时、可恢复,并记录清理范围、行数、耗时和结果。
- 备份策略要考虑日志表膨胀后的恢复窗口;如果审计合规要求长期保留,应把热库保留和冷归档保留拆开。
- 容量告警优先看趋势和剩余天数,不只看单点磁盘百分比。
故障复盘
复盘不是追责,而是改系统。
模板:
- 影响范围:用户、功能、时间窗口、数据影响。
- 时间线:发现、确认、止血、恢复、关闭。
- 根因:直接原因、触发条件、系统性原因。
- 检测:为什么被发现,为什么没有更早发现。
- 响应:哪些动作有效,哪些动作浪费时间。
- 预防:代码、配置、告警、流程、演练改什么。
- 验证:行动项如何证明完成。
复盘行动项必须可验证:
- “优化监控”不是行动项。
- “为 Outbox ERROR > 0 持续 5 分钟增加 Page 告警,并在预发验证告警触发”是行动项。
中小企业落地路线
L0:基础可恢复
- 健康检查。
- 日志和审计。
- 数据库备份。
- 关键配置不进代码。
- 手工 runbook。
L1:入口可保护
- 限流。
- 超时。
- 幂等。
- 重复提交保护。
- 线程池和连接池上限。
- 核心 API 指标。
L2:故障可隔离
- 熔断。
- 隔离池。
- Outbox。
- 任务重试和人工处理。
- readiness 摘流。
- SLO 告警。
L3:变更可控
- 灰度发布。
- 数据库兼容迁移。
- 自动回滚条件。
- 发布事件关联观测数据。
- 错误预算驱动发布节奏。
L4:持续改进
- 定期恢复演练。
- 故障注入。
- 容量复盘。
- 复盘行动项闭环。
EasyNextAdmin 应沉淀的能力
这不是现状描述,而是后续扫描清单:
| 优先级 | 能力 | 落地方向 |
|---|---|---|
| P0 | 项目级 SLO 模板 | docs/development 或部署文档 |
| P0 | liveness/readiness/startup 明确分层 | Actuator health group、Dockerfile、部署文档 |
| P0 | Feign 重试语义收敛 | EasyFeignConfig、远程调用组件文档 |
| P0 | Outbox 积压、退避和人工处理 | LocalMessageRetryJob、监控统计、页面入口 |
| P1 | 线程池、Hikari、Tomcat 容量指标 | Micrometer binder、监控页面、Grafana 样例 |
| P1 | 限流响应标准化 | 429、Retry-After、统一错误详情 |
| P1 | 发布检查和回滚模板 | docs/deployment.md、发布清单 |
| P1 | 前端稳定性观测 | Vue 全局错误、路由错误、Axios 失败事件 |
| P2 | 审计和 API 日志增长治理 | 默认时间范围、清理任务、冷归档、容量告警 |
| P2 | 备份恢复 runbook | 部署文档、运维手册 |
| P2 | 降级分级策略 | 业务模块接入清单 |
90 天落地路线
0-30 天:把故障看见
- 定义 4-6 个核心 SLO。
- 固定 Page / Ticket / Log 告警分级。
- 补核心 API、登录、任务、Outbox 指标。
- 明确 liveness/readiness/startup。
31-60 天:把故障收住
- 收敛重试语义。
- 限流返回 429 /
Retry-After。 - Outbox 增加退避、最大重试和人工处理。
- 线程池、连接池、Tomcat 容量进入面板。
61-90 天:把变更管住
- 发布检查清单。
- 数据库迁移兼容策略。
- 回滚 runbook。
- 故障复盘模板。
- 至少做一次数据库不可用、Redis 不可用或下游超时演练。