Dubbo下一站:Apache顶级项目


导读:

近日,在Apache Dubbo开发者沙龙杭州站的活动中,阿里巴巴中间件技术专家曹胜利(展图)向开发者们分享了Dubbo2.7版本的规划。

本文将为你探秘 Dubbo 2.7背后的思考和实现方式。

作者:(按姓氏拼音排序,排名不分先后)

曹胜利(展图):Apache Dubbo Committer。

刘军(陆龟):Apache Dubbo Committer。

Dubbo 2.7 将围绕 异步支持优化、元数据改造,引入JDK8的特性、Netty4.0的特性以及MetricsAPI 5个方面提升服务调用和服务治理的效率,以及可扩展性,同时将修复社区提出的若干问题。

据悉,2.7.x会作为Dubbo在Apache社区的毕业版本,Dubbo将有机会成为继RocketMQ后,来自阿里巴巴的又一个Apache顶级项目(TLP)。

优化对异步的支持
基于Dubbo实现全异步编程,是在2.7.0版本中对现有异步方式增强后新引入的功能。之前的版本对异步支持用起来不是很友好,存在若干问题,2.7版本将基于JDK8 中的CompletableFuture做出一些针对性的增强,同时新增了@Dubboasync的注解,通过这个注解可以生成异步化相关的代码。

? 2.6.x版本之前的异步方式

在2.6.x及之前的版本提供了一定的异步编程能力,包括Consumer端异步调用、参数回调、事件通知等。但当前的异步方式存在以下问题:

Future获取方式不够直接;

Future接口无法实现自动回调,而自定义ResponseFuture虽支持回调但支持的异步场景有限,如不支持Future间的相互协调或组合等;

不支持Provider端异步

以Consumer端异步使用方式为例:

1、定义一个普通的同步接口并声明支持异步调用

public interface FooService {
String findFoo(String name);}

<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">
<dubbo:method name="findFoo" async="true" /> </dubbo:reference>
2、通过RpcContext获取Future

// 此调用会立即返回nullfooService.findFoo(fooId);// 拿到调用的Future引用,当结果返回后,会被通知和设置到此FutureFuture<Foo> fooFuture = RpcContext.getContext().getFuture();fooFuture.get();

// 此调用会立即返回nullfooService.findFoo(fooId);// 拿到Dubbo内置的ResponseFuture并设置回调ResponseFuture future = ((FutureAdapter)RpcContext.getContext().getFuture()).getFuture();future.setCallback(new ResponseCallback() {br/>@Override
public void done(Object response) {
System.out.print(response);
}

@Override
public void caught(Throwable exception) {
exception.printStackTrace();
}});
从这个简单的示例我们可以体会到一些使用中的不便之处:

findFoo的同步接口,不能直接返回代表异步结果的Future,通过RpcContext进一步获取。
Future只支持阻塞式的get()接口获取结果。
通过获取内置的ResponseFuture接口,可以设置回调。但获取ResponseFuture的API使用不便,且仅支持设置回调其他异步场景均不支持,如多个Future协同工作的场景等。
? 2.7.0基于CompletableFuture的增强

了解Java中Future演进历史的同学应该知道,Dubbo 2.6.x及之前版本中使用的Future是在Java 5中引入的,所以存在以上一些功能设计上的问题,而在Java 8中引入的CompletableFuture进一步丰富了Future接口,很好的解决了这些问题。

Dubbo在2.7.0版本已经升级了对Java 8的支持,同时基于CompletableFuture对当前的异步功能进行了增强。

1、支持直接定义返回CompletableFuture的服务接口。通过这种类型的接口,我们可以更自然的实现Consumer、Provider端的异步编程。

public interface AsyncService {
CompletableFuture<String> sayHello(String name);}
2、如果你不想将接口的返回值定义为Future类型,或者存在定义好的同步类型接口,则可以额外定义一个异步接口并提供Future类型的方法。

public interface GreetingsService {
String sayHi(String name);}

@AsyncFor(GreetingsService.class)public interface GrettingServiceAsync extends GreetingsService {
CompletableFuture<String> sayHiAsync(String name);}
这样,Provider可以只实现sayHi方法;而Consumer通过直接调用sayHiAsync可以拿到一个Future实例,Dubbo框架在Provider端会自动转换为对sayHi方法的调用。为每个同步方法提供一个异步方法定义会比较麻烦,更进一步的,利用Dubbo生态中的AnnotationProcessor实现,可以自动帮我们自动生成异步方法定义。

3、同样的,如果你的原始接口定义不是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;
}}
在方法体的开始RpcContext.startAsync()启动异步,并开启新线程异步的执行业务逻辑,在耗时操作完成后通过asyncContext.write将结果写回。

4、RpcContext直接返回CompletableFuture

CompletableFuture<String> f = RpcContext.getContext().getCompletableFuture();
以上所有的增强,是在兼容已有异步编程的基础上进行的,因此基于2.6.x版本编写的异步程序不用做任何改造即可顺利运行。

元数据改造
元数据的改造主要是从适配微服务注册中心、配置中心分离的模型、减轻注册中心压力、提高服务治理能力和效率的角度来执行的。目前版本的Dubbo在注册中心的URL有数十个key/value的键值对,包含了一个服务的所有元数据。在大规模实践的基础上,我们逐渐发现这样组织的元数据存在一些问题:

注册中心存储的URL过长:
导致存储压力骤增,变更事件的推送效率明显下降;同时给订阅方带来了额外的计算压力,尤其是大规模场景下的内存,增长显著。

注册中心承担了过多服务治理配置的功能:
负责初始配置的同步,同时负责存储各种运行期配置规则。这一方面加剧了注册中心的压力,另一方面配置规则的灵活性也受到了一定的限制,同时也无法利用一些更专业的微服务配置中心带来的强大功能。

属性的功能定位不清晰:
methods, pid, owner看起来都是为服务查询服务而注册的属性,但当我们实际开发或操作服务管控系统时,却发现这样简陋的信息是很难满足查询治理需求的。我们更多的属性,需要更丰富的注册数据。以methods为例,虽然方法列表的内容已经很长了,但当我们要在OPS开发服务测试/mock功能时,却发现需要的方法签名等数据还是无法获取。

概括以上问题,我们将URL中的元数据划分了三个部分:

元数据信息
接口的完整定义:包含接口名,接口所含的方法,以及方法所含的出入参信息。对于服务测试和服务mock有非常重要的作用。

执行链路上数据
需要将参数从provider端传递给消费者端,让消费者端感知到的。如token,timeout等。

服务自持有配置&Ops需求
只有在provider端或者消费者端需要使用的,如executes, document等。

支持配置中心
配置中心是dubbo.properties的动态版本,支持的粒度包括全局的、应用级别的和服务级别的等维度。通过上面的元数据改造,配置中心支持,再加上原有的注册中心,Dubbo体系里就会存在:

注册中心:
理想情况下,注册中心将只用于关键服务信息(核心链路)的同步,进一步减轻注册中心的存储压力,提高地址同步效率,同时缓解当前由于URL冗余在大规模推送时造成的Consumer端内存计算压力。

配置中心:
解决当前配置和地址信息耦合的问题,通过抽象动态配置层,让开发者可以对接微服务场景下更常用的、更专业的配置中心,如Nacos, Apollo, Consul, Etcd等;提供更灵活的、更丰富的配置规则,包括服务、应用不同粒度的配置,更丰富的路由规则,集中式管理的动态参数规则等。

服务查询治理中心(含元数据)
对于纯粹的服务查询相关的数据,包括Consumer的服务订阅数据,往往都是注册后不可变的并且不需要节点间的同步,如当前URL可以看到的methods、owner等key以及所有的Consumer端URL。

因此我们在2.7.0中引入了存储模块,专门用来存放这部分数据,这部分将会和新版本的Dubbo-ops密切整合,作为丰富的服务查询、测试等功能的数据基础,因此这部分的数据将会得到进一步的丰富。总体来说否开启此功能对用户将是可选的,并且实现上也将是可扩展的,如我们计划支持Redis, Zookeeper等。

路由规则
Dubbo 提供了具有一定扩展性的路由规则,其中具有代表性的是条件路由和脚本路由。2.6.x及以下版本存在的问题:

路由规则存储在注册中心
只支持服务粒度的路由,应用级别无法定义路由规则
支持路由缓存,但基本不具有扩展性
一个服务或应用允许定义多条路由规则,服务治理无法管控
实现上,每条规则生成一个Router实例并动态加载
从问题出发我们重新设计,将原来的路由配置从注册中心迁往配置中心。明确了配置和服务发现的边界。新增了RouterChain,用于重构路由规则逻辑,新增应用级别路由,Tag路由优化等。针对服务级别的路由,精确到单个服务,避免了无法明确路由规则的问题。

我们简单概括下各个类的协作关系。

RegistryDirectory,包含完整的地址列表,直接对接注册中心,并动态接收注册中心地址变更。
RouterChain,由Router组装成的列表,是路由动作的入口,接收传入的地址列表并将过滤后的地址列表返回给调用方,而具体的过滤动作则委托给Router执行
Router,接收并解析路由规则,接收地址列表,根据路由规则完成过滤动作,并返回过滤后的地址列表。其本身也是一个ConfigurationListener,随时接收路由规则更新。
ConfigurationListener,动态配置变更的回调接口
DynamicConfiguration,动态配置SPI,支持的扩展实现包括Zookeeper、Apollo、Nacos等
Dubbo 将在近期正式发布2.7.0版本,恰值Dubbo宣布重启一周年。这一年,Dubbo 共发布了13个版本,社区共有24位PPMC/Committer,144位Contributor,在北京、上海、深圳、成都和杭州举办了5场开发者沙龙,但技术开源的道路并没有止境,我们欢迎更多的开发者们可以参与进来,并到Dubbo meetup来进行分享,一起建设Dubbo生态。

Dubbo下一站:Apache顶级项目

原文地址:http://blog.51cto.com/14031893/2329543

时间: 2024-10-06 09:01:07

Dubbo下一站:Apache顶级项目的相关文章

Apache顶级项目介绍7 - HBase

今天我们来继续介绍Apache顶级项目大数据三巨头之一的HBase.恰逢今天(5.24)是HBase Con2016旧金山盛会,比较应景,而且还有朋友@Luke Han去演讲Kylin. 1. 官网简介: 老样子,HBase官网的介绍, "HBase is the Hadoop database, a distributed, scalable, big data store.",所以HBase   =  Hadoop Database,并且提供了分布式可扩展的数据存储.(HBase的

Apache顶级项目介绍2-Kafka

Apache顶级项目介绍系列-1,我们从Kafka说起.why?流行 + 名字cool. Kafka官网是见过比较简单,直叙的网站,"kafka是一个高吞吐的分布式的消息系统". Kafka最初起家于LinkedIn,当时原本作为linkedin用来管理活动流(PV,用户行为分析,搜索情况)和运营数据处理的pipline的基础. 因为其分布式以及高吞吐被广泛使用,如与Cloudera, Hadoop, Storm, Spark etc. kafka首先作为一个消息系统,提供了基本功能,

Apache顶级项目介绍6 - Spark

火花四溢,热情洋溢.极客朋友么知道,我们翘首以盼的Spark来了. 提及Spark, 这几年如日中天,谈到大数据如果不提及Spark, Hadoop,就好比这年代带耳机不是2B的,你都不好意思带.Spark最初由加州大学伯克利分校(太屌的大学,出了多少名人,名作啊)的AMPLab Matei为主的小团队使用Scala开发,其核心代码只有63个Scala文件(早期版本,这里提及一下Scala语言又是一个创时代的大作,有人说它太锋利,有人说它太妖魔). Spark作者Matei: Spark于201

Apache顶级项目介绍系列1-概览

我们希望开始介绍一整套精华Apache TLP顶级项目介绍,包括Kafka, Zookepper, Hadoop, Spark, HBase etc.   公众号:技术极客TechBooster

Apache顶级项目介绍4 - Hadoop

大象起舞,天下太平,极客们应该知道我们的重量级人物Hadoop登场了. 提到Hadoop, 正所谓饮水思源,我们不得不提及一下Hadoop之父,其对技术界的影响,在近10年可谓重大, 他就是Doug Cutting, 其传奇人生及其大作这里不赘述了,大家可以Google/Bing一下,之后或许我们会推出一些技术大牛的介绍以及好书推荐. 值得提及的是Hadoop之所以诞生于2005-2006之际,是Doug当时受到来自 Google Lab公开发布的几篇paper启发,包括Map/Reduce(2

Apache孵化器主席Justin Mclean:如何成为Apache顶级开源项目

摘要: 近日,Apache孵化器主席.Apache基金会成员.Dubbo & RocketMQ等开源项目的导师Justin Mclean来到阿里巴巴西溪园区,与众多开发者分享了如何打造一个Apache顶级项目,以及项目孵化过程会遇到的一些盲点和挑战. 近日,Apache孵化器主席.Apache基金会成员.Dubbo & RocketMQ等开源项目的导师Justin Mclean来到阿里巴巴西溪园区,与众多开发者分享了如何打造一个Apache顶级项目,以及项目孵化过程会遇到的一些盲点和挑战.

盘点Apache毕业的11个顶级项目

自1999年成立至今,Apache 软件基金会已成功建立起自己强大的生态圈.其社区涌现了非常多优秀的开源项目,同时有越来越多国内外项目走向这个国际开源社区进行孵化.据悉,目前所有的 Apache 项目都需要经过孵化器孵化,满足一系列质量要求之后才可毕业.从孵化器里毕业的项目,要么独立成为顶级项目,要么成为其他顶级项目的子项目. 为便于大家了解 Apache 孵化的标准,本文盘点了 Apache 从2016年1月1日至2017年1月19日所有孵化成功并独立管理的顶级项目,共有11个.同时,欢迎大家

Apache Drill 成为 Apache 基金会顶级项目

Apache 基金会今天宣布 Apache Drill 成为基金会的顶级项目.项目新的首页是:http://drill.apache.org/ 为了帮助企业用户寻找更为有效.加快Hadoop数据查询的方法,Apache软件基金会发起了一项名为"Drill"的开源项目.Apache Drill 实现了 Google's Dremel. 该项目将会创建出开源版本的谷歌Dremel Hadoop工具(谷歌使用该工具来为Hadoop数据分析工具的互联网应用提速).而"Drill&qu

顶级项目孵化的故事系列——Kylin的心路历程【转】

现在已经名满天下的 Apache Kylin,是 Hadoop 大数据生态系统不可或缺的一部分,要知道在 Kylin 项目早期,可是以华人为主的开源团队,一路披荆斩棘经过几年的奋斗,才在 Apache 基金会牢牢的巩固了自己的位置.作为本土第一个进入到世界顶级基金会的项目,Kylin 的经验是值得大家学习的. 以下内容根据 COSCon'17讲师史少锋(Apache Kylin PMC&Committer .Kyligence 技术合伙人兼高级架构师)的演讲速记所整理. 演讲实录 今天我主要介绍