您的位置:首页 > 其它

Dubbo源码解析 —— 逻辑层设计之服务降级

2018-02-16 00:00 591 查看

作者:肥朝
原文地址:https://www.jianshu.com/p/302af7836a59友情提示:欢迎关注公众号【芋道源码】。?关注后,拉你进【源码圈】微信群和【肥朝】搞基嗨皮。友情提示:欢迎关注公众号【芋道源码】。?关注后,拉你进【源码圈】微信群和【肥朝】搞基嗨皮。友情提示:欢迎关注公众号【芋道源码】。?关注后,拉你进【源码圈】微信群和【肥朝】搞基嗨皮。

前言

dubbo服务暴露
系列完结之后,按计划来说是应该要开启
dubbo服务引用
的讲解.但是现在到了年尾,一些朋友也和我谈起了明年跳槽的事.跳槽这件事,无非也就两个原因,一个是钱没给够,另一个是心里委屈了.首先钱没给够这件事我就不多说什么了,因为每个人都觉得自己钱没给够.那心里为啥委屈了?作为一个技术人,我认为心里委屈,无非也就是两个原因,一个是在公司得不到重视,另一个是感觉学不到东西,得不到成长.感觉我所了解到的情况,往往是后者居多.这道理也简单,我们小时候看重的是兴趣和爱好,长大后看重的是投资和回报.互联网行业加班是常态,首先我不反对加班.但是加班带来的影响也不得不重视.首先对于老板而言,员工加班越多,获得的利润更大.比如:我们老板来上班事开了一辆崭新的兰博基尼。
我说:“哇喔,这辆车好牛逼”
他回答:“如果你努力工作,全身心投入,力求卓越,那么我明年还会再有一辆”。再次,一旦你加班多了,学习新技术的时间就少,这样你就会变得越来越不自信,自然不敢随便跳槽.但是加班和学习其实并不冲突.即使加班再多(比如今天周六我也还在加班),肥朝每周一篇dubbo源码解析与你不见不散,请放心保持密切关注肥朝.如果你是因为学不到东西跳槽,那么往往会遇到一个问题,那就是公司的项目太low,找一下家的时候拿不出手.技术上,增删改查这种东西肯定是拿不出手的,我用
freemarker + mybatis generator
做代码生成器直接一键生成就可以直接运行跑起来.业务上,每个公司的业务都不同,讨论意义不大.想去网上找点资料装逼,但是却发现无从下手.好不容易找了点技术沙龙逼格高的PPT,不幸的是都是空谈理论,无法和自己公司的项目衔接起来.但是幸运的是无意中关注了肥朝.首先我们来看看,我在三张图看清项目结构提到的中小型公司比较典型的Java项目的架构.从中可以看出,典型的就是三层结构,
接入层
,
逻辑层
,
数据存储层
.

当然也可以分成四层
接入层
,
逻辑层
,
原子服务层
,
数据存储层
.

当然是可以分成五层
接入层
,
序列化层(异步消息队列)
,
原子服务层
,
数据层
,
数据存储层
.

当然分几层都要根据自身业务,好的架构并不是一蹴而就,而是逐渐演变的过程.从标题就可以知道,本篇着重介绍
逻辑层
的设计(那剩下的什么时候讲?反正每周一篇,一年也就48篇.dubbo系列完结之后下一个系列由你来定,你可以自己估算一下时间).既然是设计,那么就不能纸上谈兵,必须站在巨人的肩膀上,比如孙玄老师分享的58同城架构设计就很有参考意义.我简单用思维导图做了个总结.如下:看到这里有朋友可能就不乐意了,不要扯这些原则,老子拿起键盘就是干.我想说的是,如果没有读万卷书,即使行了万里路,也不过是个邮差.知道了理论,下面我们直入主题,开始实战.

插播面试题

谈一下你们项目架构设计(很多人在回答这个的时候都容易回答
SSH
或者
SSM
,注意,所谓是
SSH
这些是技术选型,不是架构的设计)
既然你们项目用到了dubbo,那你讲讲你们是怎么通过dubbo实现服务降级的,降级的方式有哪些,又有什么区别?
dubbo监控平台能够动态改变接口的一些设置,其原理是怎样的?
既然你说你看过dubbo源码,那讲一下有没有遇到过什么坑?(区分度高,也是检验是否看过源码的试金石)

直入主题

我们从两个角度来分析,一个是
为什么需要服务降级
,一个是
怎么做服务降级

为什么需要服务降级

引进一个新技术,必须要看这个新技术解决了什么问题.比如服务降级,他解决了什么问题?从上面的思维导图我们就知道,当网站处于高峰期时,并发量大,服务能力有限,那么我们只能暂时屏蔽边缘业务.那么具体的例子是什么?比如在某宝某东购物,当支付完成,会向你推荐一些商品.但是在11大促中,并发量过大.我们就要保证"支付"这些核心业务的正常运行,因此像"推荐商品"这些边缘业务,我们就可以不调用,从而减少一定的并发.但是如果双11我先把"推荐商品"接口的代码屏蔽起来,等过后我再打开.这种太简单粗暴的方法肯定不是我们的理想追求,这时候我们就需要一个"服务开关"一样的东西.这个开关,就是
服务降级

怎么做服务降级

空谈误国,实战兴邦,光知道思维导图上的这些设计原则还不行,我们以
dubbo
为例,实战一下服务降级.首先dubbo中的服务降级分成两个屏蔽(mock=force)
容错(mock=fail)
这两个有什么区别呢?我们引用文档介绍
mock=force:return+null
 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
还可以改为 mock=fail:return+null
 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。那么下面分别演示一下容错的使用方法首先我们打上断点,造成请求超时,报错如下配置容错报错信息立刻消除,结果如下屏蔽就不在演示,配置方式类似,效果自己调试.其实从文档介绍我们就能回答出两者的区别.但是老司机可能更享受的是扒光原理的快感.

源码分析

首先我假设你之前看过肥朝每周一篇dubbo源码解析,那么对
MockClusterInvoker
这个类就不会陌生,那么我们直接看核心代码(应群友反馈,尝试一下代码不贴图)从
no mock(正常情况)
,
force:direct mock(屏蔽)
,
fail-mock(容错)
三种情况我们也可以看出,普通情况是直接调用,容错的情况是调用失败后,返回一个设置的值.而屏蔽就很暴力了,直接连调用都不调用,就直接返回一个之前设置的值.
public Result invoke(Invocation invocation) throws RpcException {
   Result result = null;
   String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
   if (value.length() == 0 || value.equalsIgnoreCase("false")){
       //no mock
       result = this.invoker.invoke(invocation);
   } else if (value.startsWith("force")) {
       if (logger.isWarnEnabled()) {
           logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " +  directory.getUrl());
       }
       //force:direct mock
       result = doMockInvoke(invocation, null);
   } else {
       //fail-mock
       try {
           result = this.invoker.invoke(invocation);
       }catch (RpcException e) {
           if (e.isBiz()) {
               throw e;
           } else {
               if (logger.isWarnEnabled()) {
                   logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " +  directory.getUrl(), e);
               }
               result = doMockInvoke(invocation, e);
           }
       }
   }
   return result;
}

敲黑板画重点

有句话叫
尽信书不如无书
,dubbo中也难免存在一些bug,比如我之前在dubbo源码解析-router就提到过,这个监控平台是有bug的,如今又出现了你会发现点删除或者点启用和禁用后,会出现多条.解决办法还是和之前一样.清除zookeeper上的节点信息(不懂的可以点回去看看
router
这篇,这就是我之前反复强调的,一定要系统学习,因为之前提到的我往往一笔带过)从这个解决bug中,我们也应该有一些逆向思维.为什么这个监控平台这么神奇,能动态改变接口的一些默认设置?你清除了zookeeper节点,监控平台上的一些配置信息就消失了,很明显,他这个原理就是改变注册在zookeeper上的节点信息.从而zookeeper通知重新生成invoker(这些具体细节在
zookeeper创建节点
,
zookeeper连接
,
zookeeper订阅
中都详细讲了,这里不再重复)当然除了这些坑外,dubbo在集群容错算法中的轮询就有个坑,需要调节当前时间解决(因为这个使用不多,这里暂时不细说),但是当当网的
dubbox
有一个坑就比较明显.如下图,当你传的参数为
null
时,这里就有很明显的空指针在后面当当网也解决了这个问题当然他这个修复的代码也可以出一个面试题.当然这道题我就不解答了java中 || 和 | 有什么区别

把握重点

看到这里你就必须要把握一下重点.从标题你就知道,本篇是有三个关键词,分别是
dubbo
,
逻辑层设计
,
服务降级
我用dubbo演示一种服务降级的方式,并不代表是只有这一种方式,你如果仔细看思维导图就明白,其实也还有很多实现方式.另外如果你觉得你们项目比较low,那么你可以设想,假如用思维导图的这些原则来设计,那么要怎么设计,有什么优缺点?然后自己尝试改造一下,这思考和行动的过程,才是你最宝贵的收获,也是我想传达的学习思想.如果你把重点当成了
dubbo如何配置服务降级
,那么可能再好的项目,你都只看到了
增删改查
.

写在最后

写到这里的时候,不知不觉已经是凌晨四点.因为996的模式下,要坚持每周一篇对我来说也是一个挑战,但是同时我也享受着这种挑战的感觉.每次下班的时候,遇到熟人都会问我怎么这么晚才下班,加班这么多,一定很多加班费吧.我说,没有加班费,这个时候都会很自然的反驳到,没有加班费那干嘛加班.同样的道理,一些朋友看到我写博客,也会问,你每周都坚持写博客有钱赚吗,我说没有,这个时候正常的逻辑也是反驳到,没有钱干嘛要做.其实有时候,博客既是写给别人看的,也是写给自己看的.最重要的是从一件事上,看到一个人做事的决心期待下周与你相遇.鉴于本人才疏学浅,不对的地方还望斧正,也欢迎关注我的简书,名称为
肥朝
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: