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

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> Dubbo源码解析 —— 逻辑层设计之服务降级

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

作者:肥朝 原文地址: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源码,那讲一下有没有遇到过什么坑?(区分度高,也是检验是否看过源码的试金石)
  • 既然你们项目用到了dubbo,那你讲讲你们是怎么通过dubbo实现服务降级的,降级的方式有哪些,又有什么区别?

    既然你说你看过dubbo源码,那讲一下有没有遇到过什么坑?(区分度高,也是检验是否看过源码的试金石)

    直入主题

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

    为什么需要服务降级

    引进一个新技术,必须要看这个新技术解决了什么问题.比如服务降级,他解决了什么问题?从上面的思维导图我们就知道,当网站处于高峰期时,并发量大,服务能力有限,那么我们只能暂时屏蔽边缘业务.那么具体的例子是什么?

    比如在某宝某东购物,当支付完成,会向你推荐一些商品.但是在11大促中,并发量过大.我们就要保证”支付”这些核心业务的正常运行,因此像”推荐商品”这些边缘业务,我们就可以不调用,从而减少一定的并发.但是如果双11我先把”推荐商品”接口的代码屏蔽起来,等过后我再打开.这种太简单粗暴的方法肯定不是我们的理想追求,这时候我们就需要一个”服务开关”一样的东西.这个开关,就是 服务降级

    怎么做服务降级

    空谈误国,实战兴邦,光知道思维导图上的这些设计原则还不行,我们以 dubbo为例,实战一下服务降级.首先dubbo中的服务降级分成两个

  • 屏蔽(mock=force)
  • 容错(mock=fail)
  • 容错(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的模式下,要坚持每周一篇对我来说也是一个挑战,但是同时我也享受着这种挑战的感觉.每次下班的时候,遇到熟人都会问我怎么这么晚才下班,加班这么多,一定很多加班费吧.我说,没有加班费,这个时候都会很自然的反驳到,没有加班费那干嘛加班.同样的道理,一些朋友看到我写博客,也会问,你每周都坚持写博客有钱赚吗,我说没有,这个时候正常的逻辑也是反驳到,没有钱干嘛要做.其实有时候,博客既是写给别人看的,也是写给自己看的.最重要的是从一件事上,看到一个人做事的决心

    期待下周与你相遇.鉴于本人才疏学浅,不对的地方还望斧正,也欢迎关注我的简书,名称为 肥朝

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> Dubbo源码解析 —— 逻辑层设计之服务降级


     上一篇
    分布式事务 TCC-Transaction 源码分析 —— 事务恢复 分布式事务 TCC-Transaction 源码分析 —— 事务恢复
    摘要: 原创出处 http://www.iocoder.cn/TCC-Transaction/transaction-recovery/ 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 TCC-Transaction 1.2.3.3
    2021-04-05
    下一篇 
    从零开始的Spring Security OAuth2(三) 从零开始的Spring Security OAuth2(三)
    上一篇文章中我们介绍了获取token的流程,这一篇重点分析一下,携带token访问受限资源时,内部的工作流程。 @EnableResourceServer与@EnableAuthorizationServer还记得我们在第一节中就介绍过了O
    2021-04-05