微服务设计—微服务可靠性

2020-05-21 00:00:00 故障 服务 系统 下游 实例

在软件的世界中,故障无处不在。硬盘可能损坏,网络可能中断,消息可能丢失,内存可能跳变。在一个大规范的分布式软件系统中,各种各样的故障层出不穷。很多时候我们期望能够预防故障的出现,但事实上这几乎是一个不可能实现的梦想。

因此我们需要转变思路,从避免故障出现转向使故障出现时对我们系统不产生影响。现在很多IT公司都参考Netflix的Chaos Monkey对系统进行故障注入测试,比如复位一个VM机,或提升CPU/IO使用率,或是耗尽磁盘空间等故障。这些故障注入甚至会在生产环境中进行,因此所有开发人员很清楚他们开发出的应用必须能够应对这些故障,而不是祈祷一切正常。

功能降级

在一个Monolithic系统中不需要考虑系统降级的问题,因为系统不是好的就是坏的。但在一个微服务系统中,任何一个系统都可能出错。比如在某宝的主页上,同时需要多个服务提供信息,这些服务中的某一个可能出现异常。此时,相对于整个网站不可用,更好的方式是进行服务降级。比如在购物车服务故障的情况下,用户仍然可以浏览商品,只是在将商品添加到购物车时提示客户“服务暂不可用”。

因此对于开发人员,我们必须清楚的知道,如果我们依赖的一个服务故障了,我们要做什么处理。

断路器

当一个微服务使用另一个微服务提供的功能时,需要通过RPC/Message等方式与其通信并通常需要等待其返回响应。但请求可能因为网络故障导致丢失、或是被请求的服务异常无法响应。为避免因为这些异常导致请求方的资源耗尽,需要引入断路器。

断路器

断路器向下游系统发送心跳,或是监控对每一个下游系统的请求,一旦察觉这些下游服务出现故障,后续的请求将不会发向此实例,直到下游系统恢复正常。

舱壁

舱壁的概念来源于船舶行业。在船的某个位置破损后,能够通过隔离此舱壁以保护船的其它部位。

在服务使用多个下游服务的时候,如果一个下游服务出现了故障或是响应缓慢异常,为避免影响对其它下游服务的使用,可以引入舱壁模式。

舱壁

在使用舱壁时,需要为每一个下游服务建立一个独立的线程池,这些线程池彼此隔离,因此在一个下游服务出现故障时,并不会影响到对其它下游服务的使用。

冗余

对于一个高可用的服务,必须具备冗余能力,当一个实例故障后,可以由其它实例继续提供服务。这些实例需要被监控,并在实例故障时能够拉起新的实例。这些服务实例必须具备良好的负载均衡能力,并部署在不同的节点上(好是不同的物理机,以避免同时故障)。如果实例需要存储数据,需要通过外置的缓存或DB进行数据的存储,以保证实例故障时数据不会丢失。

冗灾

在现实世界中,我们除了面临VM或物理机的故障,有时还会有更严重的故障,比如整个数据中心可能因为断电、火灾、地震等原因故障。并不是所有的服务都需要在出现这类故障后继续可用,但我们必须分析清楚在这些场景下,我们需要提供什么级别的可靠性。

如果服务的数据并不是至关重要,并且在此故障场景下也考虑继续提供服务,那么我们可能会考虑只进行基本的可靠性,比如每天晚上定时备份数据,并在数据中心恢复后再使用备份的数据进行恢复;

如果服务的数据非常重要,则需要保证数据在写入时就进行跨数据中心的备份;

如果服务必须在此场景下继续可用,那么就需要考虑采用跨数据中心的主备、主从甚至是多活;


系列主题

微服务的定义和优缺点

微服务设计模式—API Gateway

微服务设计模式—服务注册与发现

微服务设计模式—微服务通信

微服务设计—微服务可靠性

微服务设计—微服务部署

微服务设计—将Monolithic重构为微服务

微服务设计—事件驱动架构

相关文章