十五、服务降级

  1. 业务高峰期,为了保证核心服务的 SLA,往往需要停掉一些不太重要的业务,例如商品评论、论坛或者粉丝积分等。
  2. 某些服务因为某种原因不可用,但是流程不能直接失败,需要本地 Mock 服务端实现,做流程放通。例如图书阅读,如果用户登录余额鉴权服务不能正常工作,需要做业务放通,记录消费话单,允许用户继续阅读,而不是返回失败。

这就是服务降级,分为容错降级和屏蔽降级两种模式。

1 屏蔽降级

在一个应用中,服务往往是合设的,尽管可以通过线程池隔离等方式保证服务之间的资源隔离,但是 100%的隔离是不现实的。特别是对缓存、网络 I/O、磁盘 I/O、数据库连接资源等公共依赖无法隔离,在业务高峰期时,服务往往存在激烈的竞争,导致订购等核心服务运行质量下降,影响系统的稳定运行和客户体验。

此时需要对非核心服务做强制降级,不发起远程服务调用,直接返回空、异常或者执行特定的本地逻辑,减少自身对公共资源的消费,把资源释放出来供核心服务使用。

1.1 屏蔽降级的流程

1.2 屏蔽降级的设计实现

屏蔽降级通常用于服务运行态治理,开发时不会配置,当外界的触发条件达到某个临界值时,由运维人员/开发人员决策,通过服务治理控制台,进行人工降级操作,它的取值有如下三种:

  1. mock = force: return null。不发起远程服务调用,直接返回空对象。
  2. mock = force: throw Exception。不发起远程服务调用,直接抛出指定异常。
  3. mock = force: execute Bean。不发起远程服务调用,直接执行本地模拟接口实现类。

屏蔽降级操作是可逆的,当系统压力恢复正常水平或者不再需要屏蔽降级时,可以对已经屏蔽降级的服务恢复正常。恢复之后,消费者重新调用远程的服务提供者,同时服务状态被修改为正常状态。

2 容错降级

当非核心服务不可用时,可以对故障服务做业务逻辑放通,分布式服务框架的业务放通实际属于容错降级的一种。
容错降级不仅仅只用于业务放通,它也常用于服务提供方在客户端执行容错逻辑,容错逻辑主要包括两种:

  1. RPC异常:通常指超时异常、消息解码异常、流控异常、系统拥塞保护异常等。
  2. Service异常:例如登录校验失败异常、数据库操作失败异常等。

2.1 容错降级的工作原理


容错降级与屏蔽降级的主要差异:

  1. 触发条件不同:容错降级时根据服务调用结果,自动匹配触发的;而屏蔽降级往往是通过人工根据系统运行情况手工操作触发的。
  2. 作用不同:容错降级时当服务提供者不可用时,让消费者执行业务放通:屏蔽降级的主要目的是将原属于降级业务的资源调配出来供核心业务使用。
  3. 调用机制不同:一个发起远程服务调用,一个只做本地调用。

业务放通的 Mock接口实现往往放在消费者端,主要在于提供端可能为多个消费者服务,为了解耦,单独的消费者自己进行放通。

  1. mock = fail: throw Exception。将异常转义。
  2. mock = fail: execute Bean。将异常屏蔽掉,直接执行本地模拟解耦实现类,返回 Mock接口的执行结果。

与屏蔽降级不同的是,通常在开发态,就需要指定容错降级的策略。

无论是屏蔽降级还是容错降级,都支持从消费者或者服务提供者两个维度去配置,从而消费端配置更灵活,实现差异化降级策略。
服务降级策略配置的优先级:消费者配置策略 > 服务提供者配置策略。屏蔽降级 > 容错降级。

2.2 运行时容错降级


如果开发态没有指定容错降级策略,系统上线运行后,需要临时增加容错降级策略,服务框架也需要支持在线动态增加容错降级策略,它的工作流程与屏蔽降级类似。

而在实际项目中,利用容错降级做业务放通是主要的应用场景。

3 业务层降级

实际业务开发过程中,可能会存在比较复杂的业务放通场景,例如“调用 A 服务 + 执行本地方法调用”组合成一个流程,针对这个流程的执行结果做放通,这种场景由于本地方法调用并不经过分布式服务框架,因此需要业务自己做放通处理。

服务降级并不能 100% 满足所有业务放通场景,需要业务层开发自己的降级框架。

4 个人总结

在服务化之前,业务往往需要自己实现放通逻辑或者框架,不同的业务模块,甚至不同的开发者都自己实现了一套私有的放通流程,这对项目的开发和运维都会造成很多麻烦。

更为严重的是由于没有统一的服务降级策略和框架,无法在服务治理 Portal 上进行统一线上降级,在应对业务高峰时,运维人员会力不从心,往往需要一大群开发在背后支撑,运维效率非常低下。
基于分布式服务框架的服务降级功能,有效提升线上的服务治理效率,保证服务的 SLA,尽管服务降级更多是为了提升服务线上运行质量,但是它反向对服务的设计和开发也有约束。它要求服务在设计之初就要做如下识别:

  1. 哪些服务是核心服务、哪些是非核心服务?
  2. 哪些服务支持降级,降级策略是什么?
  3. 除了服务降级之外,是否还存在更为复杂的业务放通场景,它的策略是什么?

系统的高效、健康运行仅仅依赖线上服务治理和运维是解决不了的,需要通过分布式服务框架的特性反向映射到设计和开发态,从设计阶段就开始考虑未来如何高效运维,才能在根本上提升服务和产品的质量,这也是矛盾对立和统一的一个具体体现。