Dubbo 2.7新特性之异步化改造

这是why技术的第1篇原创文章

我与Dubbo的二三事

我是2016年毕业的,在我毕业之前,我在学校里面学到的框架都是SSH,即struts+spring+hibernate,是的你没有看错,在大学里面的课本里面学的是strusts,这个还没毕业就被基本抛弃的框架。然而我大四出去实习,用的技术是SSM,即Spring,SpringMVC,Mybatis。实习的时候做的项目都是外包项目,非常传统的单体大项目,和学校里面做课程设计一样,所有的功能包括前后端都糅合在一个项目里面,根本不知道什么是分布式架构,不夸张的说,那个时候我对分布式这一块的知识无限趋近于零。

第一次接触到分布式的概念是我正式参加工作后,第一家公司属于一家互联网公司,做第三方支付。我甚至现在还记得加入这个公司之后,第一次在同事的帮助下,分别把支付服务和账务服务的Demo,两个项目,在两个IDEA中运行起来,然后我在账务服务打了一个断点,运行支付服务的测试用例,最后程序在账务服务的断点处停了下来!程序停下来的时候,我仿佛感觉看到了"神迹",颠覆了我前4年的大学学习中的固有印象!那个时候,我才知道了还有分布式这么一回事,才第一次接触到Dubbo,那个时候,程序猿的大门才向我徐徐打开,那个时候,我才知道,我一直在新手村待了4年。


Dubbo的坎坷一生

你的一生中总是会碰到几个十分神秘的人,他们看起来或者仙风道骨,或者平平无奇,他们总是问你一些终极的问题,总是会引起你的思考,你也会无情的拒绝,因为你知道,这事,不靠谱,这些人就是“算命先生”,总是问你:"你从哪里来?你往哪里去?你60岁的时候会有一道坎,了解一下?"

我不知道我的前世,也无法预知自己今生还没发生的坎,但是我知道Dubbo从哪里来,往哪里去,了解一下?

出生豪门:

2011 年 10 月 27 日,阿里巴巴开源了自己服务化治理方案的核心框架 Dubbo,服务治理的设计理念开始逐渐在国内软件行业中落地,并被广泛应用。自开源后,许多非阿里系公司选择使用 Dubbo。

半路夭折:

2012 年 10 月 23 日,Dubbo 2.5.3 发布后,在 Dubbo 开源将满一周年之际,阿里基本停止了对 Dubbo 的主要升级。

2012 年 10 月 23 日,Dubbo 2.5.3 发布后,在 Dubbo 开源将满一周年之际,阿里基本停止了对 Dubbo 的主要升级。2013 年,2014 年,更新了 2 次 Dubbo 2.4 的维护版本,然后停止了所有维护工作。至此,Dubbo 对 Spring 的支持也停留在了 Spring 2.5.6 版本上。

同行续命:

阿里停止维护和升级 Dubbo 期间,当当网开始维护自己的 Dubbo 分支版本 Dubbox,新增支持了新版本的 Spring,支持了 Rest 协议等,并对外开源了 Dubbox。同时,网易考拉也维护了自己的独立分支 Dubbok,可惜并未对外开源。

起死回生:

2017 年 9 月 7 日,Dubbo 悄悄在 GitHub 发布了 2.5.4 版本。随后,又迅速发布了 2.5.5、2.5.6、2.5.7 等版本。在 10 月举行的云栖大会上,阿里宣布 Dubbo 被列入集团重点维护开源项目,这也就意味着 Dubbo 起死回生,开始重新进入快车道。

回归正统:

2018 年 1 月 8 日,Dubbo 2.6.0 版本发布,新版本将之前当当网开源的 Dubbox 进行了合并,实现了 Dubbo 版本的统一整合。

走向巅峰:

2018年2月,阿里巴巴宣布将Dubbo捐献给apache,进入apache孵化器。

2019 年 1 月,2.7.0 release 版本发布,这个即将毕业的 apache 版本支持了丰富的新特性,全新的 Dubbo Ops 控制台。时至 5 月,Dubbo 来到了 2.7.2 版本,期间积极引入了新的特性,支持 consul,nacos,etcd 等注册中心。

2019 年 5 月 21 号,经过了漫长的孵化期,Dubbo 迎来了毕业。成为Apache基金会顶级项目。

从Dubbo的历程可以看出,Dubbo的一生是坎坷的一生,虽然半路夭折,但是最后还是走向了巅峰。不知道为什么,这个时候我想起了马云爸爸说的一句话:

阿里说:我对Dubbo没有兴趣。因为我最快乐的时候,是当当网,帮我续命的时候!

很有马云爸爸的气质,一脉相承,厉害厉害!


Dubbo的异步化改造

Dubbo2.7新特性包括但不限于如下几点:

1.异步化改造

2.三大中心改造

3.服务治理增强

本文主要分享Dubbo2.7新特征之一,异步化改造相关的内容。

Dubbo的四种调用方式:

此图是本文的核心,本文分享的内容基本上都是对于此图深入到源码解级别的解析:

1.oneway --- 有去无回

oneway 指的是客户端发送消息后,不需要接受响应。对于那些不关心服务端响应的请求,比较适合使用 oneway 通信。但是请注意,返回值定义为void的并不是oneway的调用方式,void表示的程序上不需要关心返回值,但是对Dubbo框架而言,还是需要构建返回数据的。

仔细看oneway调用方式的图,可以看出:从客户端到服务端,只有req,没有resp;所以客户端不需要阻塞等待。

2.sync --- 同步调用

sync是最常用的通信方式,也是Dubbo默认的通信方法。

还是仔细看sync调用方式的图,再想一想你自己写的Dubbo应用,或者公司其他的Dubbo应用,是不是就是你们现在正在使用的通信方式。客服端发起req请求到A服务端,然后在设置的超时时间内,一直等待A服务器的响应resp,这个时候,我们说客户端处于阻塞的状态。当A服务器返回resp后,客户端才会继续运行。

3.future和callback --- 异步调用

future 和 callback 都属于异步调用的范畴,我们放在一起讨论。

继续仔细看future和callback调用方式的图,可以看出他们的区别是:在接收响应时,future.get() 会导致线程的阻塞;callback 通常会设置一个回调线程,当接收到服务端响应时,自动执行,不会对当前线程造成阻塞。

源码之下无秘密

1.Dubbo 2.6.0中体现调用方式的关键代码

有了前面的四种调用方式的简单介绍铺垫。我们深入到源码中一探究竟:

上图是Dubbo2.6.0版本DubboInvoke.doInvoke()方法的截图,先看个全局的代码。

其中的箭头解释一下:

箭头1:表明这段代码的版本,Dubbo2.6.0版本。

箭头2:判断调用方式是否是oneway模式,即有去无回调用。

箭头3:判断调用是否是否是async模式,即异步调用。

箭头4:既不是有去无回(oneway),也不是 异步调用(async),那么就是sync模式,即同步调用。

对于红框中的代码,放大如下:

接下来对关键代码进行解读:

1.首先,Dubbo是怎么判断调用方式是前面说的4种调用方式(对于Dubbo2.6.x来说,其实是3种,2.7.0之后才支持了callback的调用方式)的哪一种的呢?

可以看到这两行代码:

boolean isAsync = RpcUtils.isAsync(getUrl(), invocation); boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);

可以对着关键代码解读的图来看,这两行代码的用途,就是判断你的配置文件(注解的方式或者dubbo.xml)中有没有配置async=true或者return=true。

2.接下来我们重点看一下我说的“最骚”的这一行代码:

真的"骚"啊,当是异步调用的时候,Dubbo把future放到RpcContext的上下文中,然后构造一个空的RpcResult给调用方,调用方再从上下文中把future取出来,需要用返回的值的时候调用一下future.get()方法。完成异步调用的操作。

同步调用的时候,dubbo也有拿到了这个future,但是并没有返回,而是直接调用了future.get()方法,这就是同步调用。

综上:我认为同步调用和异步调用的区别就是谁去调用future.get()方法。如果是Dubbo调用则是同步调用,如果是客户端调用者是异步方法。

2.Dubbo 2.7.0中体现调用方式的关键代码

接下来,我们看一下Alibaba提供给Apache的初始版本,即2.7.0版本中体现调用方式的关键代码。

朋友们可以先看左上角,确实是Dubbo2.7.0版本的代码。然后红框中圈起来的代码,看起来和Dubbo2.6.0版本中的差不多,那我们就对比着看。

看到这个地方的时候我曾经走了一点弯路,甚至走上了歧途,一度质疑Dubbo的这个地方的源码是有问题的,毕竟我们搞技术的,就是一个大胆假设,小心求证吧。所以我给Dubbo提了一个issus.如下:

这里就不讲我走上歧途的过程了,后面有机会再分享。大家可以去看看,会不会被固化思维给带偏了。

这里的两个回答,第一个解答了我的问题,我看了后恍然大悟,这题属于当局者迷旁观者清。

第二个回答,建议我看一下最新版本的代码,当时的最新版本的代码是2.7.3。所以我把2.7.3版本的代码拉了下来。

3.Dubbo 2.7.3中体现调用方式的关键代码

接下来,我们就看看2.7.3中体现调用方式的关键代码,请各位朋友坐稳扶好,这里变化较大,车速较快,非常优秀。

首先我们可以看到isOneway的判断还是我们熟悉的代码。但是这里只有一个if-else了。Dubbo调用有四种方式,if判断了isOneway,那么剩下的三种都在这个else里面啦。

看到这里,笔者冷静的思考了一下,剩下的三种调用方式,sync调用,future调用,callback调用。其中sync调用是默认的方式,没有在这个地方体现出来,那么直觉告诉我在某个地方一定有一个异步转同步的调用。于是乎,我发现了这样一个神奇的类:

AsyncToSyncInvoker方法中的54行asyncResult.get(),其中asyncResult继承自Future,用源码说话:

接着我们说说AsyncToSyncInvoker方法中的53行,getInvokeMode().

getInvokeMode()是RpcInvocation里InvokeMode的get方法。而且2.6.0里面RpcInvocation是没有invokeMode这个成员变量的。是2.7.0版本后新加的。

至此,基本圆满了。感谢大神指引我看最新版本的代码。

然后在上一个对比图:

Show me the code

Dubbo 2.6.0的异步化实现:

1.dubbo.xml配置,加入async="true"

<dubbo:reference id="asyncService" interface="org.apache.dubbo.demo.api.AsyncService" async="true"/>

2.dubbo接口定义:

public interface AsyncService{ String sayHello(String name);}

3.异步调用,从RpcContext上下文中取出future,然后调用这个最"骚"的future.get()方法。还记得之前说的嘛:同步调用和异步调用的区别就是谁去调用future.get()方法。这里是客户端调用,所以是异步调用。

AsyncService.sayHello("hello");Future<String> fooFuture=RpcContext.getContext().getFuture();fooFuture.get();

有几个弊端:

1.不太符合异步编程的习惯,需要从一个上下文类中获取到 Future

2.如果多个异步调用,使用不当很容易造成上下文污染

3.Future 并不支持 callback 的调用方式

Dubbo 2.7.x的异步化实现:

无需相关配置中进行特殊配置,显示声明异步接口即可:

public interface AsyncService{ String sayHello(String name); default CompletableFuture<String> sayHiAsync(String name){ return CompletableFuture.completedFuture(sayHello(name)); }}

使用callback方式处理返回值

CompletableFuture<String> future = asyncService.sayHiAsync("hi");future.whenComplete((retValue, exception) -> { if (exception == null) { System.out.println(retValue); } else { exception.printStackTrace(); }});

那么为什么Dubbo2.7.0这样简单的几行代码就能实现异步化了呢?记住,源码之下无秘密:

完结撒花,关注我吧。下期再见,谢谢大家!

原文地址:https://www.cnblogs.com/thisiswhy/p/12019070.html

时间: 2024-08-29 09:01:22

Dubbo 2.7新特性之异步化改造的相关文章

H5新特性之语义化标签

二月底,疫情仍未过去,在家逆战学习. 说道H5新特性的语义化标签,就不得不先简单说一下它的发展史,兼容和一些语法问题. H5在经过多达近百项的修改,包括HTML和XHTML的标签,相关的API,Canvas等,性 能得到进一步提升. H5仅仅是新增添了一些内容并优化了它们,而不是全盘否定之前的旧的内容.支持Html5 的浏览器包括Firefox(火狐浏览器),IE9及其更高版本,Chrome(谷歌浏览器),Safari, Opera等以及一些国内浏览器. 对于H5语法变化不大,文件的扩展名是不变

.NET4.5新特性之异步编程(Async和Await)的使用

一.简介 首先来看看.net的发展中的各个阶段的特性:NET 与C# 的每个版本发布都是有一个"主题".即:C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#4.5异步编程 所谓的异步编程是利用CPU空闲时间和多核的特性,它所返回的Task或Task是对await的一个承诺,当任务执行完毕后返回一个结果给接收者.这里看到这个可能各位不太明白,不要紧,下面会有讲解. 二.使用说明 方法签名包含一个 Async 或 async 修饰符. 按照约定,异步方法的名

Servlet新特性:异步处理

参考: http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ 异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用: 对于使用传统的部署描述文件 (web.xml) 配置 Servlet 和过滤器的情况,Servlet 3.0 为 <servlet> 和 <

java9新特性-4-模块化系统: Jigsaw与Modularity

1.官方Feature 200: The Modular JDK 201: Modular Source Code 220: Modular Run-Time Images 260: Encapsulate Most Internal APIs 261:  Module System 282: jlink: The Java Linker   2.产生背景及意义 谈到 Java 9 大家往往第一个想到的就是 Jigsaw 项目.众所周知,Java 已经发展超过 20 年(95 年最初发布),Ja

Atitit.atiJsBridge 新特性v7q329

atiJsBridge 未来计划 Postdata  图像上传的支持 Simp param计划 p1 p2 p3 p4 $method 的simple ,,>> $m $index 的支持 V8 新特性 使用组件化模式,将api——url内置.. 通用化+配置  创建一个组件.. $trigger的支持 $view的支持 $partition $patitionDefine $tableDefine 作者::  ★(attilax)>>>   绰号:老哇的爪子 ( 全名::A

H5、C3、ES6的新特性

H5的新特性 1.语义化标签 有利于SEO,有助于爬虫抓取更多的有效信息,爬虫是依赖于标签来确定上下文和各个关键字的权重. 语义化的HTML在没有CSS的情况下也能呈现较好的内容结构与代码结构 方便其他设备的解析 便于团队开发和维护 2.表单新特性 3.多媒体视频(video)和音频(audio) 4.web存储 sessionstorage:关闭浏览器清空数据,储存大小约5M. localstorage:永久生效,存储大小20M,多窗口下都可以使用 都只能储存字符串 C3的新特性 1.选择器:

H5,C3,ES6新特性

H5的新特性 1.语义化标签 有利于SEO,有助于爬虫抓取更多的有效信息,爬虫是依赖于标签来确定上下文和各个关键字的权重. 语义化的HTML在没有CSS的情况下也能呈现较好的内容结构与代码结构 方便其他设备的解析 便于团队开发和维护 2.表单新特性 3.多媒体视频(video)和音频(audio) 4.web存储 sessionstorage:关闭浏览器清空数据,储存大小约5M. localstorage:永久生效,存储大小20M,多窗口下都可以使用 都只能储存字符串 C3的新特性 1.选择器:

【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就具体看看编译器到底在背后帮我们做了哪些复杂的工作的. 二.同步代码存在的问题 对于同步的代码,大家肯定都不陌生,因为我们平常写的代码大部分都是同步的,然而同步代码却存在一个很严重的问题,例如我们向一个Web服务器发出一个

h5新特性

  CSDN博客 Gane_Cheng HTML5新特性浅谈 发表于2016/10/17 21:25:58  7809人阅读 分类: 前端 转载请注明出处: http://blog.csdn.net/gane_cheng/article/details/52819118 http://www.ganecheng.tech/blog/52819118.html (浏览效果更好) 2014年10月29日,W3C宣布,经过接近8年的艰苦努力,HTML5标准规范终于制定完成. HTML5将会取代