dubbo 服务降级

1.开关 

        先讲一下开关的由来,例如京东在6月18日做店庆促销活动,在交易下单环节,可能需要调用A、B、C三个接口来完成,但是其实A和B是必须的,C只是附加的功能(例如在下单的时候做一下推荐),可有可无,在平时系统没有压力,容量充足的情况下,调用下没问题但是在类似店庆之类的大促环节,系统已经满负荷了,这时候其实完全可以不去调用C接口,怎么实现这个呢?改代码?no,no,no,这样太不敏捷,此时开关诞生了,开发人员只要简单执行一下命令或者点一下页面,就可以关掉对于C接口的调用,在大促过去之后,再把开关恢复回去即可。

2.什么是服务降级

          服务降级,当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。

3.服务降级方式:

  • 服务接口拒绝服务:无用户特定信息,页面能访问,但是添加删除提示服务器繁忙。页面内容也可在Varnish或CDN内获取。
  • 页面拒绝服务:页面提示由于服务繁忙此服务暂停。跳转到varnish或nginx的一个静态页面。
  •  延迟持久化:页面访问照常,但是涉及记录变更,会提示稍晚能看到结果,将数据记录到异步队列或log,服务恢复后执行。
  •  随机拒绝服务:服务接口随机拒绝服务,让用户重试,目前较少有人采用。因为用户体验不佳。

 

      经过过12306抢票的人应该经常会遇到这个问题:在抢票高峰的时候,明明票还有,但是查询出来的列表却是为空的(如果没票列表也应该会呈现);等高峰过后再查询,列表又恢复正常。个人猜测应该是查询过程中出现了问题,要么超时,要么网络问题导致查询失败采用的服务降级处理。所以,最终呈现给用户的并不是内部系统出错之类的提示,而是一个空的列表。好了,言归正传,在dubbo中想实现服务降级,需要怎么样做可以实现?

 

4 dubbo降级服务    
dubbo开发中,通常是微服务架构,那么在使用过程中可能会遇到多种问题:

1)多个服务之间可能由于服务没有启动或者网络不通,调用中会出现远程调用失败;

2) 服务请求过大,需要停止部分服务以保证核心业务的正常运行;

以上两个问题可以使用Dubbo的服务降级来实现;
即:在服务宕掉或者并发数太高导致的RpcException异常时,进行友好的处理或者提示,而不是内部报错导致系统不可用。也停掉非核心调用,减轻服务器压力

 

解决方法:
dubbo提供了mock配置,可以很好的实现dubbo服务降级,
mock主要有两种配置方式,

第1种
直接返回一个固定的字符串
具体配置:
在服务调用方配置mock参数: 直接定义返回值
<dubbo:reference id="xxxService" interface="com.x..service.xxxxService" check="false" mock="return 123456..." />

说明:配置了mock参数之后,假设在调用服务的时候,远程服务没有启动,或者各种网络异常了,那远程服务会把这个mock配置的值返回,也就是会返回123456...
通过这种方式就可以避免了因为服务调用不了而出现异常错误而带来的程序不可用(起码是有值返回的,然后可以根据值进行业务逻辑处理判断等等)。
注:除了配置mock参数之外,其它地方不用变。

 

第2种
根据自定义mock业务处理类进行返回     mock值设置为boolean 类型
具体配置:
在服务调用方配置mock参数:
<dubbo:reference id="xxxService" interface="com.x..service.xxxxService" check="false" mock="true" />

说明:配置了mock参数之后,假设在调用服务的时候,远程服务没有启动,或者各种网络异常了,那远程服务会去寻找自定义的mock业务处理类进行业务处理。
因此还需配置一个自定义mock业务处理类
在接口服务xxxxService的目录下创建相应的mock业务处理类,同时实现业务接口xxxxService(),接口名要注意命名规范:接口名+Mock后缀,mock实现需要保证有无参的构造方法。

 

//要实现接口,并实现相关方法 

public class xxxxServiceMock implements xxxxService {

    //降级时用到
    @Override
    public String getXXXX(int id) {
        return "this is exception 自定义....";
    }
}

 配置完成后,此时如果调用失败会调用自定义的Mock业务实现(即上面的实现类中对应方法  getXXXX)。

 

5 管理界面手动配置

以上的配置其实除了在代码中配置之外,还可以在dubb-adming管理界面直接手动配置:

分别是屏蔽和容错:

屏蔽:force.mock (即:屏蔽请求,直接返回某个值,如上面的字符串,mock="return 123456...");

容错:fail.mock  (即:允许请求,在请求失败的时候,再返回某个值,如:mock="fail:return 123456...");

 

 

6、思考

    通过例子可以知道,通过mock的配置,可以很好的实现dubbo服务降级。但是,比如例子里,接口IUser本身定义了两个接口,一个是新增用户,一个是根据id查询用户信息。对于根据id查询用户信息,在调用失败的时候返回null很好理解,可能是由于验证失败或者记录删除了,但是对于新增用户,可能就需要抛出具体的业务信息,否则程序无法处理后续的业务,包括页面弹出”添加成功“或者列表刷新的时候无法查看到最新的记录,这样体验将会非常不好。所以,如果要有较好的区分,可以通过以下的方式,可以更好的实现降级:

(1)将接口进行归类,查询类和变更操作类:对于查询的分为一个接口类,变更的归类为其他的接口类,这样对于查询的可以使用mock="return null"进行降级操作对于变更类的,可以仍旧使用try……catch进行异常捕获处理

(2)配置mock="true",同时mock实现接口,接口名要注意命名规范:接口名+Mock后缀。此时如果调用失败会调用Mock实现的方法。mock实现需要保证有无参的构造方法。

 

posted on 2020-08-10 23:04  鑫男  阅读(727)  评论(0编辑  收藏  举报

导航