大促或者业务高峰时,为了保证核心服务的SLA(Service Level Agrement服务等级协议),往往需要停掉一些不太重要的服务,例如商品评论、论坛或者粉丝积分等。
另外一种场景就是某些服务因为某种原因不可用,但是流程不能直接失败,需要本地Mock服务端实现,做流程放通。
上述两种场景都是服务降级。服务降级主要包括容错降级和屏蔽降级两种。
- 屏蔽降级
对非核心服务做强制降级,不发起远程服务调用,直接返回空、异常或者执行特定的本地逻辑,减少自身对公共资源的消费,把资源释放出来供核心服务使用。
1.1屏蔽降级的全流程如下所示
1.1 屏蔽降级的设计实现
屏蔽降级通常用于服务运行态治理,开发时不会配置,当外界的触发条件达到某个临界值时,由运维人员/开发人员决策,进行人工降级操作。取值有下面三种方式:
- mock=force: return null。不发起远程调用,直接返回空对象。
- mock=force: throw Exception。不发起远程调用,直接抛出指定异常。
- mock=force: execute Bean<beanName>。不发起远程调用,直接执行本地模拟接口实现类。
对于第三种降级策略,被执行的Spring Bean需要实现服务提供者的接口,代码示例如下:
Public interface xxxService(){
Object xxxMethod(Object req);
}
本地Mock的Bean实现示例如下:
Public interface xxxServiceMock implements xxxService(){
Object xxxMethod(Object req){
//本地mock逻辑代码实现
}
}
服务发布模型中,需要支持服务降级属性,它的配置示例如下:
<xxx:service interface="org.yuanrj.demo.EchoService" ref="echoService" mock="force: execute Bean:echoServiceMock">
- 容错降级
当非核心服务不可用时,可以对故障服务做业务放通,分布式服务框架的业务放通实际属于容错降级的一种。
容错降级除了业务放通,还用于服务提供方在客户端执行容错逻辑。
容错逻辑主要包括两种:
- RPC异常:通常指超时异常,消息解码异常、流控异常、系统拥塞保护异常等。
- Service异常:例如登录校验失败异常、数据库操作失败异常等。
2.1容错降级的流程图
2.2屏蔽降级与容错降级的差异
注意:业务放通的Mock接口往往放在消费者端,主要原因是:
- 执行本地业务放通,可能会依赖消费者本地独有的资源,如消费者依赖的服务,数据结构,数据库资源等。这个逻辑搬到服务提供者实现,会导致系统间耦合。
- 不同的消费者,消费同一个服务提供者时,对失败之后的处理策略存在差异。若把这些差异都搬到服务端的Mock接口实现,会造成代码臃肿,很难维护。
2.3容错降级的策略
- mock=force: throw Exception。将异常转义。
- mock=force: execute Bean<beanName>。将异常屏蔽掉,直接执行本地模拟接口实现类。
消费者配置示例如下:
<bean class="org.yuanrj.demo.XXXAction" interface="org.yuanrj.demo.EchoService"
actives="5" mock="force: execute Bean:echoServiceMock"/>
服务降级策略配置的优先级为:消费者配置策略>服务提供者配置策略,屏蔽降级高于容错降级。
参考资料
《分布式服务框架原理与实践》