内容: 记录微服务的故障及处理方法

微服务故障类型:

1、集群故障。微服务系统一般都是集群部署的,根据业务量大小而定,集群规模从几台到甚至上万台
都有可能。一旦某些代码出现 bug,可能整个集群都会发生故障,不能提供对外提供服务。

2、单IDC故障。现在大多数互联网公司为了保证业务的高可用性,往往业务部署在不止一个IDC。
然而现实中时常会发生某个IDC的光缆因为道路施工被挖断,导致整个IDC脱网。

IDC就是数据中心的意思!

3、单机故障。顾名思义就是集群中的个别机器出现故障,这种情况往往对全局没有太大影响,
但会导致调用到故障机器上的请求都失败,影响整个系统的成功率。

微服务故障解决方法:

1、集群故障
集群故障的产生原因一般有两种:
1、一种是代码 bug 所导致,比如说某一段代码不断地分配大对象,但没有及时回收导致OOM;
2、另一种是突发的流量冲击,超出了系统的最大承载能力,比如“双 11”这种购物活动,电商
系统会在零点一瞬间涌入大量流量,超出系统的最大承载能力,一下子就把整个系统给压垮了。

应付集群故障的思路,主要有两种:限流和降级

* 限流
顾名思义,限流就是限制流量,通常情况下,系统能够承载的流量根据集群规模的大小是固定的,
可以称之为系统的最大容量。当真实流量超过了系统的最大容量后,就会导致系统响应变慢,服务
调用出现大量超时,反映给用户的感觉就是卡顿、无响应。所以,应该根据系统的最大容量,给系
统设置一个阈值,超过这个阈值的请求会被自动抛弃,这样的话可以最大限度地保证系统提供的服
务正常。

除此之外,通常一个微服务系统会同时提供多个服务,每个服务在同一时刻的请求量也是不同的,
很可能出现的一种情况就是,系统中某个服务的请求量突增,占用了系统中大部分资源,导致其他
服务没有资源可用。因此,还要针对系统中每个服务的请求量也设置一个阈值,超过这个阈值的请
求也要被自动抛弃,这样的话不至于因为一个服务影响了其他所有服务。

在实际项目中,可以用两个指标来衡量服务的请求量,一个是 QPS 即每秒请求量,一个是工作线
程数。不过 QPS 因为不同服务的响应快慢不同,所以系统能够承载的 QPS 相差很大,因此一般
选择工作线程数来作为限流的指标,给系统设置一个总的最大工作线程数以及单个服务的最大工作
线程数,这样的话无论是系统的总请求量过大导致整体工作线程数量达到最大工作线程数,还是某
个服务的请求量超过单个服务的最大工作线程数,都会被限流,以起到保护整个系统的作用。

* 降级
什么是降级呢?在我看来,降级就是通过停止系统中的某些功能,来保证系统整体的可用性。
降级可以说是一种被动防御的措施,为什么这么说呢?因为它一般是系统已经出现故障后所采取
的一种止损措施。那么降级一般是如何实现的呢?根据我的实践来看, 一种可行的方案是通过
开关来实现。具体来讲,就是在系统运行的内存中开辟一块区域,专门用于存储开关的状态,
也就是开启还是关闭。并且需要监听某个端口,通过这个端口可以向系统下发命令,来改变
内存中开关的状态。当开关开启时,业务的某一段逻辑就不再执行,而正常情况下,开关是
关闭的状态。

开关一般用在两种地方,一种是新增的业务逻辑,因为新增的业务逻辑相对来说不成熟,
往往具备一定的风险,所以需要加开关来控制新业务逻辑是否执行;另一种是依赖的服务
或资源,因为依赖的服务或者资源不总是可靠的,所以最好是有开关能够控制是否对依赖
服务或资源发起调用,来保证即使依赖出现问题,也能通过降级来避免影响。

在实际业务应用的时候,降级要按照对业务的影响程度进行分级,一般分为三级:
一级降级是对业务影响最小的降级,在故障的情况下,首先执行一级降级,所以一级降级也
可以设置成自动降级,不需要人为干预;二级降级是对业务有一定影响的降级,在故障的
情况下,如果一级降级起不到多大作用的时候,可以人为采取措施,执行二级降级;三级
降级是对业务有较大影响的降级,这种降级要么是对商业收入有重大影响,要么是对用户
体验有重大影响,所以操作起来要非常谨慎,不在最后时刻一般不予采用。


2、单IDC故障

在现实情况下,整个 IDC 脱网的事情时有发生,多半是因为不可抗力比如机房着火、光缆被
挖断等,如果业务全部部署在这个 IDC,那就完全不可访问了,所以国内大部分的互联网业务
多采用多 IDC 部署。具体来说,有的采用同城双活,也就是在一个城市的两个 IDC 内部署;
有的采用异地多活,一般是在两个城市的两个 IDC 内部署;当然也有支付宝这种金融级别的
应用采用了“三地五中心”部署,这种部署成本显然高比两个 IDC 要高得多,但可用性的保障
要更高。

采用多 IDC 部署的最大好处就是当有一个 IDC 发生故障时,可以把原来访问故障 IDC 的流
量切换到正常的 IDC,来保证业务的正常访问。

流量切换的方式一般有两种,一种是基于 DNS 解析的流量切换,一种是基于 RPC 分组的流量切换。

* 基于 DNS 解析的流量切换:
基于 DNS 解析流量的切换,一般是通过把请求访问域名解析的 VIP 从一个 IDC 切换到另外一个
 IDC。比如访问“www.weibo.com”,正常情况下北方用户会解析到联通机房的 VIP,南方用户会
 解析到电信机房的 VIP,如果联通机房发生故障的话,会把北方用户访问也解析到电信机房的VIP,
 只不过此时网络延迟可能会变长。

* 基于 RPC 分组的流量切换
对于一个服务来说,如果是部署在多个 IDC 的话,一般每个 IDC 就是一个分组。假如一个 IDC 
出现故障,那么原先路由到这个分组的流量,就可以通过向配置中心下发命令,把原先路由到这个
分组的流量全部切换到别的分组,这样的话就可以切换故障 IDC 的流量了。

3、单机故障

单机故障是发生概率最高的一种故障了,尤其对于业务量大的互联网应用来说,上万台机器的规模也
是很常见的。这种情况下,发生单机故障的概率就很高了,这个时候只靠运维人肉处理显然不可行,
所以就要求有某种手段来自动处理单机故障。

处理单机故障一个有效的办法就是自动重启。具体来讲,你可以设置一个阈值,比如以某个接口的
平均耗时为准,当监控单机上某个接口的平均耗时超过一定阈值时,就认为这台机器有问题,这个
时候就需要把有问题的机器从线上集群中摘除掉,然后在重启服务后,重新加入到集群中。

不过这里要注意的是,需要防止网络抖动造成的接口超时从而触发自动重启。一种方法是在收集
单机接口耗时数据时,多采集几个点,比如每 10s 采集一个点,采集 5 个点,当 5 个点中
有超过 3 个点的数据都超过设定的阈值范围,才认为是真正的单机问题,这时会触发自动重启
策略。

除此之外,为了防止某些特殊情况下,短时间内被重启的单机过多,造成整个服务池可用节点数
太少,最好是设置一个可重启的单机数量占整个集群的最大比例,一般这个比例不要超过 10%,
因为正常情况下,不大可能有超过 10% 的单机都出现故障。