容灾与隔离

服务容灾与隔离

从一个计算机系统的角度讲,一切引起系统非正常停机的事件都可以称为灾难。大致可以分成以下三个类型:

  • 自然灾害,包括地震、火灾、洪水、雷电等,这种灾难破坏性大,影响面广;

  • 设备故障,包括主机的 CPU、硬盘等损坏,电源中断以及网络故障等,这类灾难影响范围比较小,破坏性小;

  • 人为操作破坏,包括误操作、人为蓄意破坏等等;

容灾(Disaster Tolerance),就是在上述的灾难发生时,在保证生产系统的数据尽量少丢失的情况下,保持生存系统的业务不间断地运行。异地多活、同城双活都属于容灾的范畴。容灾需要具备较为完善的数据保护与灾难恢复功能,保证生产中心不能正常工作时数据的完整性及业务的连续性,并在最短时间内由灾备中心接替,恢复业务系统的正常运行,将损失降到最小。

Netflix 则完全基于 AWS 云基础设施,认为都有可能发生任何的故障,更何况资源也不掌握在自己手上。Netflix 基于 Design for Failure 理念却构建出用户无感知的高可用系统,支撑他的业务飞速发展。Design for Failure 是 AWS 设计的一条最佳实践,假定任何环节都有可能出问题,然后倒推依次设计。

  • 假设你的硬件会失败...

  • 假设电力停机...

  • 假设会遭遇自然灾难...

  • 假设伴随着时间,你的应用软件会失败...

  • 假设人员会错误操作...

以 Netflix 公布的数据来看,每个 EC2 实例平均生命周期只有 36 个小时,每个单点不断地重生,才能达到整体的高可用性。其关键实施要点总结如下:

  • 容错:当系统中出现了各种故障时,系统能够自动隔离故障而不影响系统对外的服务质量;

  • 冗余:提供系统冗余配置,当系统发生故障时,冗余的快速介入并承担已发生故障的工作;

单点故障

单点故障(single point of failure,缩写 SPOF)是指系统中一旦失效,就会让整个系统无法运作的部件,换句话说,单点故障即会整体故障。打个简单的比方,一个加工厂流水线只有甲乙丙丁四名员工,一个加工需求进来,需要甲乙丙丁依次处理方能完成,此时针对流水线的作业,四名员工就是链路的单点,任何一人请假或者离职,流水线作业就无法正常,此时就形成了单点故障。

单点故障不仅仅出现在计算机领域,所有领域都有这个问题。根据航空行业标准 HB 6486-2008 中的定义,单点故障指 “无余度装置或装置的无余度部分出现的故障”。在飞机设计过程中,单点故障一般指会引起飞机/系统故障,而且没有冗余措施或替代的操作程序作为补救的产品故障。由此可见,单点故障可导致飞机出现灾难级影响。

首先,单点故障会带来系统可靠性的下降,单点故障可能会引发整体故障。另外一点,就是单点会带来性能问题,影响系统的处理能力。

系统隔离

在微服务架构中,我们经常会提到雪崩效应(Avalanche Effect)这一概念。服务雪崩的产生是一种扩散效应。当系统中存在两个服务 A 和 B,如果 A 服务出现问题,而 B 服务会通过用户不断提交服务请求等手工重试或代码逻辑自动重试等手段进一步加大对 A 服务的访问流量。因为 B 服务使用同步调用,会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,B 服务提供的服务本身也将处于不可用状态,整个过程的演变可参考下图。而这一效果在整个服务访问链路上进行扩散,就形成了雪崩效应。

雪崩效应的预防需要依赖于架构设计中的一种称为舱壁隔离(Bulkhead Isolation)的架构模式。所谓舱壁隔离,顾名思义就是像舱壁一样对资源或失败单元进行隔离,如果一个船舱破了进水,只损失一个船舱,其他船舱可以不受影响。舱壁隔离模式在微服务架构中的应用就是各种服务隔离思想。

在计算机系统里,将系统依赖的资源(线程、CPU)和服务隔离开来能够使得某个服务的故障不会影响其他服务的调用。通过线程池或者分散部署结点可以对故障进行隔离。此外,为不同的用户提供单独的访问通道,不仅仅能够做故障隔离,也有利于做用户权限控制。大家常见的隔离技术有:

  • 隔离硬件:虚拟机

  • 隔离操作系统:容器虚拟化

  • 隔离底层:Servlet 容器

  • 隔离依赖版本:虚拟环境

  • 隔离运行环境:语言虚拟机

  • 隔离语言:DSL

隔离是微服务架构中最重要的特性,也是实现反应式宣言中所提倡的弹性、可伸缩系统的前提。所谓弹性,就是从失败中恢复的能力,依赖于这种舱壁和失败隔离的设计,并且需要打破同步通信机制。由此,微服务一般是在边界之间使用异步消息传输,从而使得正常的业务逻辑避免对捕获错误、错误处理的依赖。

当然,我们使用了容器等虚拟化技术天然就采用了隔离技术。