资讯专栏INFORMATION COLUMN

dubbo源码解析(四十三)2.7新特性

qqlcbb / 2658人阅读

摘要:大揭秘目标了解的新特性,以及版本升级的引导。四元数据改造我们知道以前的版本只有注册中心,注册中心的有数十个的键值对,包含了一个服务所有的元数据。

DUBBO——2.7大揭秘
目标:了解2.7的新特性,以及版本升级的引导。
前言

我们知道Dubbo在2011年开源,停止更新了一段时间。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本。随后,版本发布的非常迅速,Dubbo项目被重启了,经过大半年的更新,在2018年2月15日,Dubbo 获得了 14 张赞成票,在无弃权和反对票的情况下,正式通过投票,顺利成为 Apache 基金会孵化项目。现在的Dubbo社区非常活跃,版本进度也非常的快。

从上图就可以看出dubbo现在的活跃度。

现在dubbo项目有以下几个分支:

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新特性介绍。我就在分享者的基础上讲解一下自己的理解。

正文 (一)JDK版本

在所需的最小JDK版本从以前的1.6变成了1.8。

(二)包重命名

com.alibaba.dubbo - > org.apache.dubbo

(三)异步支持优化

我们知道dubbo协议本身支持三种发送请求方式:

单向发送:执行方法不需要返回结果

同步发送:执行方法后,等待结果返回,否则一直阻塞.

异步发送:也就是当我发送调用后,我不阻塞等待结果,直接返回,将返回的future保存到上下文,方便后期使用。在异步发送中有两种方式分别是

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 sayHello(String name);
}

如果你不想将接口的返回值定义为Future类型,或者存在定义好的同步类型接口,则可以额外定义一个异步接口并提供Future类型的方法。

public interface GreetingsService {
    String sayHi(String name);
}
@AsyncFor(GreetingsService.class)
public interface GrettingServiceAsync extends GreetingsService {
    CompletableFuture 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新增了什么。下一篇我就先从源码的角度来讲讲这个异步化的改造。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73948.html

相关文章

  • dubbo源码解析四十八)异步化改造

    摘要:大揭秘异步化改造目标从源码的角度分析的新特性中对于异步化的改造原理。看源码解析四十六消费端发送请求过程讲到的十四的,在以前的逻辑会直接在方法中根据配置区分同步异步单向调用。改为关于可以参考源码解析十远程通信层的六。 2.7大揭秘——异步化改造 目标:从源码的角度分析2.7的新特性中对于异步化的改造原理。 前言 dubbo中提供了很多类型的协议,关于协议的系列可以查看下面的文章: du...

    lijinke666 评论0 收藏0
  • dubbo源码解析四十七)服务端处理请求过程

    摘要:而存在的意义就是保证请求或响应对象可在线程池中被解码,解码完成后,就会分发到的。 2.7大揭秘——服务端处理请求过程 目标:从源码的角度分析服务端接收到请求后的一系列操作,最终把客户端需要的值返回。 前言 上一篇讲到了消费端发送请求的过程,该篇就要将服务端处理请求的过程。也就是当服务端收到请求数据包后的一系列处理以及如何返回最终结果。我们也知道消费端在发送请求的时候已经做了编码,所以我...

    yzzz 评论0 收藏0
  • dubbo源码解析四十六)消费端发送请求过程

    摘要:可以参考源码解析二十四远程调用协议的八。十六的该类也是用了适配器模式,该类主要的作用就是增加了心跳功能,可以参考源码解析十远程通信层的四。二十的可以参考源码解析十七远程通信的一。 2.7大揭秘——消费端发送请求过程 目标:从源码的角度分析一个服务方法调用经历怎么样的磨难以后到达服务端。 前言 前一篇文章讲到的是引用服务的过程,引用服务无非就是创建出一个代理。供消费者调用服务的相关方法。...

    fish 评论0 收藏0
  • dubbo源码解析四十二)序列化——开篇

    摘要:在版本中,支持五种序列化方式,分别是依赖阿里的库,功能强大支持普通类包括任意或完全兼容序列化协议的系列化框架,序列化速度大概是的倍,大小是大小的左右。但这里实际不是原生的序列化,而是阿里修改过的,它是默认启用的序列化方式自带的序列化实现。 序列化——开篇 目标:介绍dubbo中序列化的内容,对dubbo中支持的序列化方式做对比,介绍dubbo-serialization-api下的源码...

    keke 评论0 收藏0
  • dubbo源码解析四十一)集群——Mock

    摘要:源码分析一创建该类是服务降级的装饰器类,对进行了功能增强,增强了服务降级的功能。注意隐式契约尽管描述被添加到接口声明中,但是可扩展性是一个问题。获得服务类型获得创建加入集合该方法是获得。 集群——Mock 目标:介绍dubbo中集群的Mock,介绍dubbo-cluster下关于服务降级和本地伪装的源码。 前言 本文讲解两块内容,分别是本地伪装和服务降级,本地伪装通常用于服务降级,比如...

    ivydom 评论0 收藏0

发表评论

0条评论

qqlcbb

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<