DUBBO——2.7大揭秘
目标:了解2.7的新特性,以及版本升级的引导。
前言
咱们知道Dubbo在2011年开源,中止更新了一段时间。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本。随后,版本发布的很是迅速,Dubbo项目被重启了,通过大半年的更新,在2018年2月15日,Dubbo 得到了 14 张同意票,在无弃权和反对票的状况下,正式经过投票,顺利成为 Apache 基金会孵化项目。如今的Dubbo社区很是活跃,版本进度也很是的快。html

从上图就能够看出dubbo如今的活跃度。java
如今dubbo项目有如下几个分支:git
- 2.5.x:该分支在近期投票决定再也不维护。
- 2.6.x:该分支如今还在维护中,包名前缀是com.alibaba,也是贡献给 Apache 以前的版本。
- 2.7.1-release:一个临时分支。
- 3.x-dev:将以 Streaming 为内核,重点的改变在服务治理和编程模型上。具体我也尚未深刻研究,我也会跟踪该分支的变更,敬请期待吧。
- master:目前版本是2.7.x,包名前缀是:org.apache,也是 Dubbo 贡献给 Apache 的开发版本,接下来的分析也会在2.7.1上进行分析。
关注dubbo社区的朋友应该也知道在2019.3.23在南京举办了Meetup,其中有一个专题就是讲2.7新特性介绍。我就在分享者的基础上讲解一下本身的理解。github
正文
(一)JDK版本
在所需的最小JDK版本从之前的1.6变成了1.8。redis
(二)包重命名
com.alibaba.dubbo - > org.apache.dubboapache
(三)异步支持优化
咱们知道dubbo协议自己支持三种发送请求方式:编程
- 单向发送:执行方法不须要返回结果
- 同步发送:执行方法后,等待结果返回,不然一直阻塞.
-
异步发送:也就是当我发送调用后,我不阻塞等待结果,直接返回,将返回的future保存到上下文,方便后期使用。在异步发送中有两种方式分别是segmentfault
- future:当请求有响应后,经过future.get()来得到响应结果,可是future.get()会致使线程阻塞,future从RpcContext获取。
- callback:设置一个回调线程,当接收到响应时,自动执行,不会对当前线程形成阻塞,自定义ResponseFuture支持callback。
2.6.x版本的异步方式提供了一些异步能力,包括Consumer端异步调用、参数回调、事件通知等。但当前的异步方式存在如下问题:缓存
- Future获取方式不够直接,只能在RpcContext中进行获取;
- Future只支持阻塞式的get()接口获取结果。
- Future接口没法实现自动回调,而自定义ResponseFuture虽支持callback回调但支持的异步场景有限,如不支持Future间的相互协调或组合等;
- 不支持Provider端异步
具体的能够参考该文章dubbo源码解析(二十四)远程调用——dubbo协议中的源码分析来理解其中存在的问题。异步
那么在2.7.x版本,因为JDK版本升级到了1.8,引入了JDK1.8 中的CompletableFuture接口,CompletableFuture支持 future 和 callback 两种调用方式。关于CompletableFuture怎么被运用到dubbo中我会在后续的文章介绍。引入该接口后,作了如下优化:
- 支持Provider端异步
- 支持直接定义返回CompletableFuture的服务接口。经过这种类型的接口,咱们能够更天然的实现Consumer、Provider端的异步编程。
public interface AsyncService {
CompletableFuture<String> sayHello(String name);
}
- 若是你不想将接口的返回值定义为Future类型,或者存在定义好的同步类型接口,则能够额外定义一个异步接口并提供Future类型的方法。
public interface GreetingsService {
String sayHi(String name);
}
@AsyncFor(GreetingsService.class)
public interface GrettingServiceAsync extends GreetingsService {
CompletableFuture<String> sayHiAsync(String name);
}
- 若是你的原始接口定义不是Future类型的返回值,Provider端异步也提供了相似Servlet3.0里的Async Servlet的编程接口:
RpcContext.startAsync()
public interface AsyncService {
String sayHello(String name);
}
public class AsyncServiceImpl implements AsyncService {
public String sayHello(String name) {
final AsyncContext asyncContext = RpcContext.startAsync();
new Thread(() -> {
asyncContext.write("Hello " + name + ", response from provider.");
}).start();
return null;
}
}
具体的实现原理我在后续文章中结合源码来说解,注意:这些改动都仅仅支持dubbo协议。
(四)元数据改造
咱们知道2.7之前的版本只有注册中心,注册中心的URL有数十个key/value的键值对,包含了一个服务全部的元数据。在愈来愈多的功能被增长,元数据也变得异常庞大,就出现了下面的问题:
- 注册中心存储的URL过长:这会致使存储的压力骤增,数据庞大致使在修改元数据后的通知效率也降低,而且增长了消费者对于元数据解析的压力,尤为是在大规模场景下的内存增加显著
- 注册中心承担了过多的服务治理配置的功能:初始配置的同步、存储各类运行期配置规则加重了注册中心的压力,配置规则的灵活性也有所限制,阻碍了市场上的一些优秀微服务配置中心的集成和扩展。
- 属性的功能定位不清晰:methods,pid,owner虽然是为了查询服务而注册的属性,可是这些简陋的信息很难知足查询服务治理需求,因此须要更加丰富的注册数据。例如methods,虽然方法列表的内容已经很长,可是在ops开发服务测试/mock功能时,发现须要的方法签名等数据仍是没法获取。
针对以上问题,在2.7中,将URL中的元数据划分了三个部分:
- 元数据信息:接口的完整定义,包含接口名,接口所含的方法,以及方法所含的出入参信息。对于服务测试和服务mock有很重要做用。
- 执行链路上数据:须要将参数从provider端传递给consume端,让consume端感知的到,好比token、timeout等
- 服务本身持有的配置&Ops需求:只有provider端本身须要或者consume端本身须要的数据,好比executes、document等
改造后,分别造成三大中心:
- 注册中心:理想状况下,注册中心将只用于关键服务信息(核心链路)的同步,进一步减轻注册中心的存储压力,提升地址同步效率,同时缓解当前因为URL冗余在大规模推送时形成的Consumer端内存计算压力。
- 配置中心:解决当前配置和地址信息耦合的问题,经过抽象动态配置层,让开发者能够对接微服务场景下更经常使用的、更专业的配置中心,如Nacos, Apollo, Consul, Etcd等;提供更灵活的、更丰富的配置规则,包括服务、应用不一样粒度的配置,更丰富的路由规则,集中式管理的动态参数规则等
- 服务查询治理中心:对于纯粹的服务查询相关的数据,包括Consumer的服务订阅数据,每每都是注册后不可变的而且不须要节点间的同步,如当前URL能够看到的methods、owner等key以及全部的Consumer端URL,目前支持 redis(推荐),zookeeper,将做为Dubbo-Admin支持的服务测试,模拟和其余服务治理功能的基础。
(五)服务治理规则加强
路由规则的加强
Dubbo 提供了具备必定扩展性的路由规则,其中具备表明性的是条件路由和脚本路由。2.6.x及如下版本存在的问题:
- 路由规则存储在注册中心
- 只支持服务粒度的路由,应用级别没法定义路由规则
- 支持路由缓存,但基本不具备扩展性
- 一个服务或应用容许定义多条路由规则,服务治理没法管控
- 实现上,每条规则生成一个Router实例并动态加载
在2.7.x版本中,对路由规则作了加强:
-
丰富的路由规则。
- 条件路由:支持应用程序级别和服务级别条件。
- 标记路由:新引入以更好地支持流量隔离,例如灰色部署
配置中心对服务治理的加成
- 将治理规则与注册表分离,也就是出现了配置中心,使配置中心更容易扩展。有Apollo和Zookeeper,2.7.1还支持了consul和etcd。
- 应用程序级动态配置支持。
- 使用YAML做为配置语言,更易于阅读和使用
(六)新增配置中心
配置中心(v2.7.0)在Dubbo中承担两个职责:
- 外部化配置:启动配置的集中式存储 (简单理解为dubbo.properties的外部化存储)外部化配置目的之一是实现配置的集中式管理,这部分业界已经有不少成熟的专业配置系统如Apollo, Nacos等,Dubbo所作的主要是保证能配合这些系统正常工做。外部化配置和其余本地配置在内容和格式上并没有区别,能够简单理解为
dubbo.properties
的外部化存储,配置中心更适合将一些公共配置如注册中心、元数据中心配置等抽取以便作集中管理
- 服务治理:服务治理规则的存储与通知。
配置的操做能够查看官方文档,因为如今dubbo支持多种配置方式,因此这里须要强调的是配置覆盖的优先级,从上至下优先级依此下降:

(七)序列化扩展
新增了Protobuf序列化支持。
(八)其余
其余的bug修复以及一些小细节优化请查看github上的Issues或者PR。
后记
升级2.7.0的引导请查看如下连接:
http://dubbo.apache.org/zh-cn...
该文章讲解了dubbo2.7的新特性,如今2.7.1已经发布,有兴趣的能够去看看2.7.1新增了什么。下一篇我就先从源码的角度来说讲这个异步化的改造。