稳定性的模式与反模式

稳定性之于系统,就像健康之于人类,看起来重要不紧急,然而一旦失去,就追悔莫及。

稳定性是一切 0 前面的 1。

本文简单介绍下稳定的模式和反模式,大家在设计系统的时候可以多一点思考。

稳定性的反模式:

集成点

  • 每一个依赖点的都有可能有问题。
  • 利用断路器、超时、中间件解耦和握手等模式进行防御性编程,以防止集成点出现问题。

同层连累反应

  • 例如在负载均衡下,一台服务器的停机会波及其余服务器。
  • 可以配置健康检测,有问题时,启动新的实例。

层叠失效

  • 层叠失效有一个将系统失效从一个层级传到另一个层级的机制

用户

  • 用户会消耗内存
  • 用户会做奇怪和随机的事情
  • 恶意用户

线程阻塞

  • 应用程序的失效大多与线程阻塞相关。系统失效形式包括常见的系统逐渐变慢和服务器 停止响应。线程阻塞反模式会导致同层连累反应和层叠失效。

自黑式攻击

  • 无状态、自动化扩展

放大效应

  • 留意点对点通信
  • 留意共享资源

失衡的系统容量

  • 通过测试发现系统容量失衡

一窝蜂

  • 一窝蜂是对系统的集中使用,相比将峰值流量分散开后所需的系统能力,一窝蜂需要一
    个更高的系统容量峰值。
  • 不要将所有 cron 作业都设置在午夜或其他任何整点时间执行。用混合的方式设置时间,
    分散负载。
  • 固定的重试时间间隔,会集中那段时间的调用方需求。相反,使用退避算法,不同调用
    方在经过自己的退避时间后,在不同的时间点发起调用。

做出误判的机器

  • 基础设施管理工具可以迅速对系统产生巨大的影响,要在其内部构建限制器和防护措施,防止其快速毁掉整个系统。

缓慢的响应

  • 一旦陷入响应缓慢,上游系统本身的处理速度也会随之变慢,并且当响应时间超过其自身的超时时间时,会很容易引发稳定性问题。
  • 快速失败:如果系统能跟踪自己的响应情况,那么就可以知道自己何时变慢。当系统平均响应时间 超出系统所允许的时间时,可以考虑发送一个即时错误响应。至少,当平均响应时间超 过调用方的超时时间时,应该发送这样的响应。

无限长的结果集

  • 使用切合实际的数据量。
  • 在前端发送分页请求。
  • 不要依赖数据生产者。

稳定性的模式:

良好的模式能为开发工程师提供架构和设计方面的指导, 从而减少、消除或缓解系统中的裂纹产生的影响。

超时

  • 将超时模式应用于集成点、阻塞线程和缓慢响应。
    • 超时模式可以防止对集成点的调用转变为对阻塞线程的调用,从而避免层叠失效。
  • 采用超时模式,从意外系统失效中恢复。
    • 当操作时间过长,有时无须明确其原因时,只需要放弃操作并继续做其他事。超时模式 可以帮助我们实现这一点。
  • 考虑延迟重试。
    • 大多数超时原因涉及网络或远程系统中的问题。这些问题不会立即被解决。立即重试很 可能会遭遇同样的问题,并导致再次超时。这只会让用户等待更长的时间才能看到错误 消息。大多数情况下,应该把操作任务放入队列,稍后再重试。

断路器

  • 出现问题,停止调用。
    • 断路器是保护系统免受各种集成点问题的基本模式。如果集成点出现问题,停止调用!
  • 与超时模式一起使用。
    • 当集成点出现问题时,断路器就能派上用场,避免继续调用。当使用超时模式时,表明集成点存在问题。
  • 开放、跟踪并报告断路器状态变化情况。
    • 断路器跳闸总是表明出现异常。运维工程师应该注意到这种情况,加以记录和报告,并分析其趋势和相关性。

舱壁

  • 当灾难发生时,舱壁模式将系统进行分隔,确保部分系统功能可用。
  • 选择有用的分隔粒度。
    • 可以对应用程序内的线程池进行分隔,对服务器的 CPU 进行分隔,或对集群中的服务器进行分隔。

稳态

  • 便面人为干预生产环境
  • 应用自己清理带有应用程序逻辑的数据
  • 限制缓存
  • 滚动日志

快速失败

  • 快速失败,而非缓慢响应

任其崩溃并替换

  • 通过组件崩溃保护系统。
  • 快速重启和重启归队。

握手

  • 创建基于合作的需求控制机制。
  • 考虑健康状况检查

考验机

  • 优秀的考验机可以让你模拟现实世界中的各种混乱的系统失效方式。

中间件解耦

  • 从同步的“请求回复”到异步的通信方式的转变,需要完全不同的设计。此时就需要考虑转换成本。

卸下负载

  • 通过卸下负载避免响应缓慢。

背压机制

  • 背压机制通过让消费者放慢工作来实现安全性。
    • 消费者的处理速度终究会减慢,此时唯一能做的就是让消费者“提醒”提供者,不要过 快地发送请求。
  • 在系统边界内运用背压机制。
    • 如果是跨越系统边界的情况,就要换用卸下负载模式,当用户群是整个互联网时更应如此。
  • 要想获得有限的响应时间,就需要构建有限长度的等待队列。
    • 当等待队列已满时只有以下选择(虽然都不令人愉悦):丢弃数据,拒绝工作或将其阻塞。消费者必须当心,不要永久阻塞。

调速器

  • 放慢自动化工具的工作速度,以便人工干预。
  • 在不安全的方向上施加阻力。
  • 考虑使用响应曲线。