俯瞰Dubbo全局,閱讀源碼前必須掌握這些?。?/h1>
作者個(gè)人研發(fā)的在高并發(fā)場景下,提供的簡單、穩(wěn)定、可擴(kuò)展的延遲消息隊(duì)列框架,具有精準(zhǔn)的定時(shí)任務(wù)和延遲隊(duì)列處理功能。自開源半年多以來,已成功為十幾家中小型企業(yè)提供了精準(zhǔn)定時(shí)調(diào)度方案,經(jīng)受住了生產(chǎn)環(huán)境的考驗(yàn)。為使更多童鞋受益,現(xiàn)給出開源框架地址:
https://github.com/sunshinelyz/mykit-delay
既然是要寫深度解析Dubbo源碼的系列專題,我們首先要做的就是搭建一套Dubbo的源碼環(huán)境,正所謂“工欲善其事,必先利其器”。但是,為了更好的理解Dubbo,我將本文重點(diǎn)分成三個(gè)部分:Dubbo中的核心角色、搭建Dubbo源碼環(huán)境、Dubbo核心模塊說明、運(yùn)行Dubbo的示例程序 四個(gè)部分。說干就干,上重點(diǎn)。
注:本系列專題,我是基于Dubbo 2.7.8版本進(jìn)行源碼分析的。
Dubbo中的核心角色
為了更好的說明Dubbo中的核心角色,這里,我就直接引用一張Dubbo的依賴關(guān)系圖。
注:圖片來自Dubbo官網(wǎng)。
從Dubbo的依賴關(guān)系圖中,我們可以看出,Dubbo主要由四部分構(gòu)成:Registry、Provider、Consumer和Monitor 。接下來,我們就分別對這四部分進(jìn)行簡單的介紹。
- Registry,注冊中心。在Dubbo中,注冊中心負(fù)責(zé)服務(wù)的注冊與發(fā)現(xiàn),主要就是針對服務(wù)地址的注冊與查找。值得一提的是,在Dubbo中,Provider和Consumer只有在服務(wù)啟動(dòng)的時(shí)候與注冊中心進(jìn)行交互。之后,注冊中心通過長連接的形式來感知Provider的存在,如果Provider宕機(jī)或不可用,注冊中心就會(huì)立即推送相關(guān)的事件來告知Consumer。
- Provider,服務(wù)的提供者。Provider在啟動(dòng)的時(shí)候,會(huì)向注冊中心注冊自己的相關(guān)服務(wù),主要是通過將自身的服務(wù)地址和相關(guān)的配置信息封裝成URL添加到Zookeeper等服務(wù)中。
- Consumer,服務(wù)的消費(fèi)者。Consumer在啟動(dòng)的時(shí)候,會(huì)向注冊中心訂閱其關(guān)注的服務(wù)。主要是向Zookeeper等服務(wù)中獲取Provider注冊的URL,并且在Zookeeper等服務(wù)中添加相應(yīng)的監(jiān)聽器。獲取到Provider注冊的URL之后,Consumer就會(huì)通過負(fù)載均衡算法從獲取的多個(gè)Provider中選擇一個(gè),并與其建立連接,發(fā)起RPC調(diào)用。如果Zookeeper等服務(wù)中注冊的Provider發(fā)生了變更,Consumer就會(huì)通過在注冊中心中添加的監(jiān)聽器來獲取最新的Provider信息。而且Consumer會(huì)緩存Provider的信息,如果Consumer與Provider一旦建立起連接,即使注冊中心宕機(jī)或不可用,也不會(huì)影響Consumer和Provider之間的交互。
- Monitor:監(jiān)控中心。主要用來統(tǒng)計(jì)Dubbo服務(wù)的調(diào)用次數(shù)和調(diào)用的時(shí)間。在Dubbo的核心架構(gòu)中,監(jiān)控中心不是必需的,監(jiān)控中心宕機(jī)或不可用不會(huì)影響Dubbo的整體服務(wù)。
- 好了,對于Dubbo的核心角色我們就介紹到這兒,更多的信息,小伙伴們可以參見Dubbo的官方文檔。
搭建Dubbo源碼環(huán)境
我們可以使用如下命令將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進(jìn)行編譯
- mvn clean install -Dmaven.test.skip=true
轉(zhuǎn)換成IDEA項(xiàng)目,這里我使用的是IDEA分析Dubbo源碼。
- mvn idea:idea
接下來,我們就可以將Dubbo源碼導(dǎo)入到IDEA了。
說了這么多,其中還有一種方式就是通過瀏覽器直接下載Dubbo 2.7.8的源碼到本地。
在瀏覽器中打開鏈接:https://github.com/apache/dubbo/releases/tag/dubbo-2.7.8 下載Dubbo源碼。
這里下載zip壓縮包和tar.gz壓縮包均可,下載到本地后解壓,將其導(dǎo)入到IDEA中即可。
導(dǎo)入完成后,我們看到的項(xiàng)目結(jié)構(gòu)如下所示。
接下來,我們就對Dubbo源碼中的核心模塊進(jìn)行簡單的介紹。
Dubbo核心模塊說明
dubbo-common模塊
Dubbo的公共模塊,提供了Dubbo SPI的實(shí)現(xiàn)、時(shí)間輪的實(shí)現(xiàn)、動(dòng)態(tài)編譯等通用的功能。
dubbo-remoting模塊
Dubbo的遠(yuǎn)程通信模塊,其中,dubbo-remoting-api是對整個(gè)模塊的核心抽象,其他子模塊基于其他開源框架對dubbo-remoting-api進(jìn)行實(shí)現(xiàn)。
dubbo-rpc模塊
Dubbo的RPC模塊,依賴dubbo-remoting模塊。其中,dubbo-remoting-api是整個(gè)dubbo-rpc模塊的核心抽象,其他模塊是對dubbo-remoting-api的實(shí)現(xiàn)。
dubbo-registry模塊
Dubbo中與注冊中心交互的模塊。其中dubbo-registry-api是整個(gè)dubbo-registry的核心抽象,其他模塊是對dubbo-registry-api的具體實(shí)現(xiàn)。
dubbo-config模塊
Dubbo中解析對外暴露的配置的模塊。其中,dubbo-config-api 子模塊負(fù)責(zé)處理以API 方式使用Dubbo時(shí)的相關(guān)配置,dubbo-config-spring 子模塊負(fù)責(zé)處理與 Spring 集成使用時(shí)的相關(guān)配置方式。
dubbo-metadata模塊
Dubbo中的元數(shù)據(jù)模塊。其中,dubbo-metadata-api是對整個(gè)dubbo-metadata的抽象,其他模塊是對dubbo-metadata-api的實(shí)現(xiàn)。
dubbo-configcenter模塊
Dubbo的配置中心模塊,其中,提供了多種服務(wù)發(fā)現(xiàn)的方式并接入了多種服務(wù)發(fā)現(xiàn)組件。
dubbo-monitor模塊
Dubbo 的監(jiān)控模塊,主要用于統(tǒng)計(jì)服務(wù)調(diào)用次數(shù)、調(diào)用時(shí)間以及實(shí)現(xiàn)調(diào)用鏈跟蹤的服務(wù)。
dubbo-cluster模塊
Dubbo的集群管理模塊,主要提供負(fù)載均衡、容錯(cuò)、路由等功能。
運(yùn)行Dubbo示例程序
在Dubbo源碼中,有一個(gè)示例程序模塊dubbo-demo,在運(yùn)行dubbo-demo模塊中的示例前,我們先在本地啟動(dòng)一個(gè)Zookeeper作為注冊中心。
注:小伙伴們可以自行到Apache官網(wǎng)下載Zookeeper。
Dubbo示例程序結(jié)構(gòu)
Dubbo提供的示例程序的總體結(jié)構(gòu)如下所示。
我們來看看dubbo-demo下有哪些模塊。
- dubbo-demo-interface:Dubbo示例定義的業(yè)務(wù)接口。
- 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模塊的核心代碼進(jìn)行簡單的介紹,并運(yùn)行相關(guān)的示例程序。小伙伴們可自行分析和運(yùn)行dubbo-demo-xml和dubbo-demo-api中的示例程序并運(yùn)行相關(guān)的代碼。
(1)dubbo-demo-interface:定義了業(yè)務(wù)接口。
其中,DemoService接口的核心代碼如下所示。
- package org.apache.dubbo.demo;
- import java.util.concurrent.CompletableFuture;
- public interface DemoService {
- //同步調(diào)用
- String sayHello(String name);
- //異步調(diào)用
- default CompletableFuture<String> sayHelloAsync(String name) {
- return CompletableFuture.completedFuture(sayHello(name));
- }
- }
(2)dubbo-demo-annotation:提供了基于Spring注解的示例程序。
Provider代碼
我們先來看dubbo-demo-annotation-provider模塊,也就是服務(wù)的提供者。其DemoServiceImpl的代碼如下所示。
- @DubboService
- public 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模塊的代碼,也就是服務(wù)消費(fèi)者的示例代碼。其中,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 {
- }
- }
運(yùn)行Dubbo示例程序
我們先在本地啟動(dòng)Zookeeper,然后分別運(yùn)行dubbo-demo-annotation-provider模塊的Application類和dubbo-demo-annotation-consumer模塊的Application類。
此時(shí)在IDEA的控制臺(tái)會(huì)輸出如下信息。
- result :Hello world, response from provider: 192.168.0.5:20880
Dubbo總結(jié)
到這里,我們介紹了Dubbo中的核心角色,如何搭建Dubbo源碼環(huán)境,對Dubbo源碼中的核心模塊進(jìn)行了簡單的說明,并簡單的分析了Dubbo的示例程序并運(yùn)行了示例程序。其中,在介紹和運(yùn)行示例程序時(shí),我們重點(diǎn)介紹了dubbo-demo-annotation示例模塊,小伙伴們可自行分析和運(yùn)行其他示例模塊。在后續(xù)的文章中分析源碼時(shí),我們也主要是通過debug Dubbo的示例程序的方式進(jìn)行。
本文轉(zhuǎn)載自微信公眾號「冰河技術(shù)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系冰河技術(shù)公眾號。