可靠性 是做什么的?
可靠性是一门在周围系统发生故障时仍能保持运行的学问——因为故障不可避免。优先考虑局部故障设计,正常路径自然会通畅。
规则
- 所有出站调用都必须设置超时。 没有例外。缺少超时就是一次线程池耗尽事故的导火索。
- 仅对幂等操作进行重试。 采用指数退避和抖动。重试非幂等POST操作会导致重复创建、重复扣款、重复发送邮件。
- 在可变公共API上使用幂等键。 允许客户端在网络波动时安全重试,无需你猜测结果。
- 对外部依赖采用熔断机制。 当下游服务出现故障时,快速失败既能保护你自身,也能保护下游。盲目重试会将一次故障变成两次。
- 对关键路径进行舱壁隔离。 为每个下游服务隔离线程池和连接池,避免一个慢速服务拖垮整个系统。
- 优雅降级优于硬失败。 提供过期的缓存数据、部分响应或缩减的功能集,而不是直接返回500错误。
- 避免单点故障。 每个有状态组件部署多可用区,每个无状态组件部署多个副本,负载均衡健康检查必须能够真实检测到故障。
- 关闭必须优雅完成。 清空正在处理的请求,关闭连接池,刷新缓冲区。SIGTERM → 停止接收新请求 → 完成或取消现有请求 → 退出。
- 确保任何时刻都能安全重启。 任何单个Pod都应该可以在任意时刻被杀死,且对用户造成零可见影响。如果不能,那就是需要修复的bug。
- 备份在从它恢复之前都是未经测试的。 定期进行真实的恢复演练。
危险信号
restTemplate.exchange(...)未配置超时。- 没有上限且没有退避的重试循环。
- “重新部署后就能工作。”(内存中存在隐藏状态。)
- 声称零停机部署但实际上并非零停机,因为请求在收到SIGTERM时被丢弃。
- 从未执行过的灾难恢复运行手册。