写点什么

俯瞰 Dubbo 全局,阅读源码前必须掌握这些!!

用户头像
冰河
关注
发布于: 2021 年 01 月 07 日
俯瞰Dubbo全局,阅读源码前必须掌握这些!!

写在前面


在上一篇《冰河开始对Dubbo下手了!》一文中,我们重点介绍了为何要学习 Dubbo,而且还是要深入理解 Dubbo 的原理和核心源码。既然是要写深度解析 Dubbo 源码的系列专题,我们首先要做的就是搭建一套 Dubbo 的源码环境,正所谓“工欲善其事,必先利其器”。但是,为了更好的理解 Dubbo,我将本文重点分成三个部分:Dubbo 中的核心角色、搭建 Dubbo 源码环境、Dubbo 核心模块说明、运行 Dubbo 的示例程序 四个部分。说干就干,上重点。


注:本系列专题,我是基于 Dubbo 2.7.8 版本进行源码分析的。


文章已收录到:


https://github.com/sunshinelyz/technology-binghe


https://gitee.com/binghe001/technology-binghe


Dubbo 中的核心角色


为了更好的说明 Dubbo 中的核心角色,这里,我就直接引用一张 Dubbo 的依赖关系图。



注:图片来自 Dubbo 官网。


从 Dubbo 的依赖关系图中,我们可以看出,Dubbo 主要由四部分构成:Registry、Provider、Consumer 和 Monitor 。接下来,我们就分别对这四部分进行简单的介绍。


  • Registry,注册中心。在 Dubbo 中,注册中心负责服务的注册与发现,主要就是针对服务地址的注册与查找。值得一提的是,在 Dubbo 中,Provider 和 Consumer 只有在服务启动的时候与注册中心进行交互。之后,注册中心通过长连接的形式来感知 Provider 的存在,如果 Provider 宕机或不可用,注册中心就会立即推送相关的事件来告知 Consumer。

  • Provider,服务的提供者。Provider 在启动的时候,会向注册中心注册自己的相关服务,主要是通过将自身的服务地址和相关的配置信息封装成 URL 添加到 Zookeeper 等服务中。

  • Consumer,服务的消费者。Consumer 在启动的时候,会向注册中心订阅其关注的服务。主要是向 Zookeeper 等服务中获取 Provider 注册的 URL,并且在 Zookeeper 等服务中添加相应的监听器。获取到 Provider 注册的 URL 之后,Consumer 就会通过负载均衡算法从获取的多个 Provider 中选择一个,并与其建立连接,发起 RPC 调用。如果 Zookeeper 等服务中注册的 Provider 发生了变更,Consumer 就会通过在注册中心中添加的监听器来获取最新的 Provider 信息。而且 Consumer 会缓存 Provider 的信息,如果 Consumer 与 Provider 一旦建立起连接,即使注册中心宕机或不可用,也不会影响 Consumer 和 Provider 之间的交互。

  • Monitor:监控中心。主要用来统计 Dubbo 服务的调用次数和调用的时间。在 Dubbo 的核心架构中,监控中心不是必需的,监控中心宕机或不可用不会影响 Dubbo 的整体服务。


好了,对于 Dubbo 的核心角色我们就介绍到这儿,更多的信息,小伙伴们可以参见 Dubbo 的官方文档。


搭建 Dubbo 源码环境


我们可以使用如下命令将 github 的源码下载的本地。


git clone https://github.com/apache/dubbo.git
复制代码


接下来,将 Dubbo 的源码切换到 2.7.8


git checkout -b dubbo-2.7.8 dubbo-2.7.8
复制代码


使用 Maven 进行编译


mvn clean install -Dmaven.test.skip=true 
复制代码


转换成 IDEA 项目,这里我使用的是 IDEA 分析 Dubbo 源码。


mvn idea:idea
复制代码


接下来,我们就可以将 Dubbo 源码导入到 IDEA 了。


说了这么多,其中还有一种方式就是通过浏览器直接下载 Dubbo 2.7.8 的源码到本地。


在浏览器中打开链接:https://github.com/apache/dubbo/releases/tag/dubbo-2.7.8 下载 Dubbo 源码。



这里下载 zip 压缩包和 tar.gz 压缩包均可,下载到本地后解压,将其导入到 IDEA 中即可。


导入完成后,我们看到的项目结构如下所示。



接下来,我们就对 Dubbo 源码中的核心模块进行简单的介绍。


Dubbo 核心模块说明


dubbo-common 模块


Dubbo 的公共模块,提供了 Dubbo SPI 的实现、时间轮的实现、动态编译等通用的功能。



dubbo-remoting 模块


Dubbo 的远程通信模块,其中,dubbo-remoting-api 是对整个模块的核心抽象,其他子模块基于其他开源框架对 dubbo-remoting-api 进行实现。



dubbo-rpc 模块


Dubbo 的 RPC 模块,依赖 dubbo-remoting 模块。其中,dubbo-remoting-api 是整个 dubbo-rpc 模块的核心抽象,其他模块是对 dubbo-remoting-api 的实现。



dubbo-registry 模块


Dubbo 中与注册中心交互的模块。其中 dubbo-registry-api 是整个 dubbo-registry 的核心抽象,其他模块是对 dubbo-registry-api 的具体实现。



dubbo-config 模块


Dubbo 中解析对外暴露的配置的模块。其中,dubbo-config-api 子模块负责处理以 API 方式使用 Dubbo 时的相关配置,dubbo-config-spring 子模块负责处理与 Spring 集成使用时的相关配置方式。


dubbo-metadata 模块


Dubbo 中的元数据模块。其中,dubbo-metadata-api 是对整个 dubbo-metadata 的抽象,其他模块是对 dubbo-metadata-api 的实现。



dubbo-configcenter 模块


Dubbo 的配置中心模块,其中,提供了多种服务发现的方式并接入了多种服务发现组件。



dubbo-monitor 模块


Dubbo 的监控模块,主要用于统计服务调用次数、调用时间以及实现调用链跟踪的服务。



dubbo-cluster 模块


Dubbo 的集群管理模块,主要提供负载均衡、容错、路由等功能。



运行 Dubbo 示例程序


在 Dubbo 源码中,有一个示例程序模块 dubbo-demo,在运行 dubbo-demo 模块中的示例前,我们先在本地启动一个 Zookeeper 作为注册中心。


注:小伙伴们可以自行到 Apache 官网下载 Zookeeper。


Dubbo 示例程序结构


Dubbo 提供的示例程序的总体结构如下所示。



我们来看看 dubbo-demo 下有哪些模块。


  • dubbo-demo-interface:Dubbo 示例定义的业务接口。

  • dubbo-demo-xml:提供了基于 Spring XML 的使用示例。

  • dubbo-demo-annotation:提供了基于 Spring 注解方式的使用示例。

  • dubbo-demo-api:提供了以 API 方式使用 Dubbo 的示例。


其中,dubbo-demo-xml、dubbo-demo-annotation 和 dubbo-demo-api 模块都是依赖 dubbo-demo-interface 模块的。


接下来,我们就对 dubbo-demo-interface 模块和 dubbo-demo-annotation 模块的核心代码进行简单的介绍,并运行相关的示例程序。小伙伴们可自行分析和运行 dubbo-demo-xml 和 dubbo-demo-api 中的示例程序并运行相关的代码。


(1)dubbo-demo-interface:定义了业务接口。



其中,DemoService 接口的核心代码如下所示。


package org.apache.dubbo.demo;import java.util.concurrent.CompletableFuture;public interface DemoService {    //同步调用    String sayHello(String name);    //异步调用    default CompletableFuture<String> sayHelloAsync(String name) {        return CompletableFuture.completedFuture(sayHello(name));    }}
复制代码


(2)dubbo-demo-annotation:提供了基于 Spring 注解的示例程序。


Provider 代码


我们先来看 dubbo-demo-annotation-provider 模块,也就是服务的提供者。其 DemoServiceImpl 的代码如下所示。


@DubboServicepublic class DemoServiceImpl implements DemoService {    private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override public String sayHello(String name) { logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress()); return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress(); }
@Override public CompletableFuture<String> sayHelloAsync(String name) { return null; }}
复制代码


Application 类的代码如下所示。


public class Application {    public static void main(String[] args) throws Exception {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);        context.start();        System.in.read();    }
@Configuration @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider") @PropertySource("classpath:/spring/dubbo-provider.properties") static class ProviderConfiguration { @Bean public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress("zookeeper://127.0.0.1:2181"); return registryConfig; } }}
复制代码


Consumer 代码


接下来,我们来看看 dubbo-demo-annotation-consumer 模块的代码,也就是服务消费者的示例代码。其中,DemoServiceComponent 类的代码如下所示。


@Component("demoServiceComponent")public class DemoServiceComponent implements DemoService {    @DubboReference    private DemoService demoService;
@Override public String sayHello(String name) { return demoService.sayHello(name); } @Override public CompletableFuture<String> sayHelloAsync(String name) { return null; }}
复制代码


Application 类的代码如下所示。


public class Application {    public static void main(String[] args) {        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);        context.start();        DemoService service = context.getBean("demoServiceComponent", DemoServiceComponent.class);        String hello = service.sayHello("world");        System.out.println("result :" + hello);    }
@Configuration @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.consumer.comp") @PropertySource("classpath:/spring/dubbo-consumer.properties") @ComponentScan(value = {"org.apache.dubbo.demo.consumer.comp"}) static class ConsumerConfiguration {
}}
复制代码


运行 Dubbo 示例程序


我们先在本地启动 Zookeeper,然后分别运行 dubbo-demo-annotation-provider 模块的 Application 类和 dubbo-demo-annotation-consumer 模块的 Application 类。


此时在 IDEA 的控制台会输出如下信息。


result :Hello world, response from provider: 192.168.0.5:20880
复制代码


Dubbo 总结


到这里,我们介绍了 Dubbo 中的核心角色,如何搭建 Dubbo 源码环境,对 Dubbo 源码中的核心模块进行了简单的说明,并简单的分析了 Dubbo 的示例程序并运行了示例程序。其中,在介绍和运行示例程序时,我们重点介绍了 dubbo-demo-annotation 示例模块,小伙伴们可自行分析和运行其他示例模块。在后续的文章中分析源码时,我们也主要是通过 debug Dubbo 的示例程序的方式进行。


好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,一起交流技术,一起进阶,一起牛逼~~

发布于: 2021 年 01 月 07 日阅读数: 42
用户头像

冰河

关注

公众号:冰河技术 2020.05.29 加入

Mykit系列开源框架发起者、核心架构师和开发者,《海量数据处理与大数据技术实战》与《MySQL开发、优化与运维实战》作者。【冰河技术】微信公众号作者。

评论

发布
暂无评论
俯瞰Dubbo全局,阅读源码前必须掌握这些!!