服务降级
what
当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易的能正常运行。
使用场景
当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,我们可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
核心设计
分布式开关
可以设置一个分布式开关,用于实现服务的降级,然后集中式管理开关配置信息即可。具体方案如下:
开关可由配置中心维护.
客户端 定时任务拉取配置 pull.
配置中心配置变更主动通知 所有客户端,更新内存中的配置信息 push.
自动降级
超时降级: 主要配置好 超时时间 和 超时重试次数 机制,并使用 异步机制 探测恢复情况.
失败次数降级: 主要是一些不稳定的API,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况.
故障降级: 如要调用的远程服务挂掉了(网络故障、DNS故障、HTTP服务返回错误的状态码和RPC服务抛出异常),则可以直接降级.
限流降级: 当触发了限流超额时,可以使用暂时屏蔽的方式来进行短暂的屏蔽.
比如秒杀或抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级
.
降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
服务降级-配置中心
配置中心和应用之间需要网络通信,因此可能会因网络闪断或网络重启等因素,导致配置推送信息丢失、重启或网络恢复后不能再接受、变更不及时等等情况,因此服务降级的配置中心需要实现以下几点特性,从而尽可能的保证配置变更即使达到
:
启动主动拉取配置: 用于初始化配置(减少第一次定时拉取周期).
发布订阅配置: 用于实现配置及时变更(可以解决90%左右的配置变更).
客户端定时拉取配置: 用于解决发布订阅失效或消失丢失的情况(可以解决9%左右的发布订阅失效的消息变更).
离线文件缓存配置: 用于临时解决重启后连接不上配置中心的问题.
可编辑式配置文档: 用于直接编辑文档的方式来实现配置的定义.
处理策略
当触发服务降级后,新的交易再次到达时,我们该如何来处理这些请求呢?
从微服务架构全局的视角来看,我们通常有以下是几种常用的降级处理方案:
第一部分是手动降级,代码里提前写好 if (xxFlag) 走降级逻辑,然后在配置中心配置该值.若需要降级时,修改配置中心的该值,走降级逻辑.
第二部分是自动降级,包括:
1.超时降级
当访问的数据库/HTTP 服务/远程调用响应慢或者长时间响应慢,且该服务不是核心服务的话,可以在超时后自动降级。并使用 异步机制 探测恢复情况.
比如,商品详情页上有推荐内容/评价,但是,推荐内容/评价暂时不展示,对用户购物流程不会产生很大影响。对于这种服务是可以超时降级的。如果是调用别人的远程服务,则可以和对方定义一个服务响应最大时间,如果超时了,则自动降级。注意,在实际场景中一定要配置好超时时间和超时重试次数及机制。
2.统计失败次数降级
有时依赖一些不稳定的API,比如,调用外部机票服务,当失败调用次数达到一定阈值自动降级(熔断器)。然后通过异步线程去探测服务是否恢复了,恢复则取消降级。
3.故障降级
比如,要调用的远程服务挂掉了(网络故障、DNS故障、HTTP服务返回错误的状态码、RPC服务抛出异常),则可以直接降级。降级后的处理方案有:默认值(比如库存服务挂了,返回默认现货)、兜底数据(比如广告挂了,返回提前准备好的一些静态页面)、缓存(之前暂存的一些缓存数据)。
4.限流降级
当我们去秒杀或者抢购一些限购商品时,可能会因为访问量太大而导致系统崩溃,此时,开发者会使用限流来限制访问量,当达到限流阈值时,后续请求会被降级。降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会儿重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。
针对后端代码层面的降级处理策略,则我们通常使用以下几种处理措施进行降级处理:抛异常, 返回NULL, 调用Mock数据, 调用Fallback处理逻辑
dubbo服务降级
先普通执行,执行失败之后再执行相应的mock逻辑
mock = fail:
直接执行相应的mock逻辑
mock = force
会在zk上创建configurators的子节点
MockClusterInvoker的逻辑:
首先去获取mock参数,
如果没有配置,则直接使用FailoverClusterInvoker去正常的向provider发出请求;
如果配置为以force开头的,则直接执行doMockInvoke(Invocation invocation, RpcException e),不再向provider发送请求;
如果配置为以fail开头的,则先使用FailoverClusterInvoker去正常的向provider发出请求,如果失败抛出了非业务异常,则执行doMockInvoke(Invocation invocation, RpcException e);
spring cloud hystrix
将获得的返回结果为:fallback。我们从eureka-client的控制台中,可以看到服务提供方输出了原本要返回的结果,但是由于返回前延迟了5秒,而服务消费方触发了服务请求超时异常,服务消费者就通过HystrixCommand注解中指定的降级逻辑进行执行,因此该请求的结果返回了fallback
。这样的机制,对自身服务起到了基础的保护,同时还为异常情况提供了自动的服务降级切换机制。