首頁  >  文章  >  Java  >  Dubbo源碼分析:小白入門篇

Dubbo源碼分析:小白入門篇

Java后端技术全栈
Java后端技术全栈轉載
2023-08-23 14:44:32620瀏覽


如果你已經對Dubbo熟練使用了,那這文章不太適合你,但如果想了解Dubbo,想學習Dubbo那就非常適合你。

Dubbo源碼分析:小白入門篇

什麼是Dubbo?

Dubbo一開始是由阿里巴巴開發,後面貢獻給了Apache,所以後面我們稱之為Apache Dubbo或直接叫Dubbo

Dubbo 是一款高效能、輕量級的開源服務框架 。

先修正讀法:

錯誤讀法:diubo、dubo

正確讀法:|ˈdʌbəʊ|

Dubbo的六大核心能力

  • ##以介面代理為導向的高效能
    RPC
  • 呼叫
  • 智慧容錯與負載平衡

服務自動註冊與發現

高度可擴展能力運行期流量調度

可視化的服務治理與維運。 開發中,我們都喜歡把

Dubbo
簡稱為

RPC

開源框架。

什麼是RPC? ###### ############RPC###是###Remote Procedure Call###的簡稱,翻譯過來就是:###遠端過程呼叫###。 #########簡單的理解是一個節點請求另一個節點提供的服務 。 #########通俗點講:###

兩台伺服器A和B,在伺服器A上部署一個應用程式serverA,在伺服器B上部署一個應用程式serverB。此時,serverA想呼叫serverB裡的某個方法,由於不在同一伺服器內,不能直接調用,需要透過網路來表達呼叫的語意和傳導呼叫的資料。

呼叫遠端的方法就像呼叫本地的方法一樣。

Dubbo源碼分析:小白入門篇

我們開發中,通常兩個服務(不同伺服器上的服務)之間的調用,通常都是用HTTP REST。

RPC框架

其實關於RPC框架,市面上有很多了,Dubbo只是其中一個。比如說還有:

  • gRPC 是Google 開發的高效能、通用的開源RPC 框架,gRPC 使用ProtoBuf 來定義服務,ProtoBuf 是Google 開發的一種資料序列化協議,效能比較高,壓縮和傳輸效率高,文法也比較簡單。另外,gRPC 支援多種語言,並能夠基於語言自動產生客戶端和服務端功能庫。
  • Thrift 起源於 Facebook,和 Dubbo 一樣,後來被提交給 Apache 基金會將 Thrift 作為一個開源專案。 Facebook 創造 Thrift 的目的是為了解決 Facebook 各系統間大數據量的傳輸通信,以及系統間語言環境不同需要跨平台的問題。
  • Motan 是新浪微博開源的 Java RPC 框架,官方文件對外宣傳在微博平台已經廣泛應用,每天為數百個服務完成近千億次的調用。
  • ...

Dubbo核心角色

我們來看看Dubbo架構中的核心角色:

Dubbo源碼分析:小白入門篇

#該圖來自於官網,下面我們對圖做一個簡單介紹:

Registry

註冊中心。負責服務地址的註冊與查找,服務的 ProviderConsumer 只在啟動時與註冊中心互動。註冊中心透過長連結感知 Provider 的存在,在 Provider 出現宕機的時候,註冊中心會立即推送相關事件通知 Consumer

Provider

服務提供者。在它啟動的時候,會向 Registry 進行註冊操作,將自己服務的位址和相關設定資訊封裝成 URL 新增到 ZooKeeper 中。

Consumer

服務消費者。在它啟動的時候,會向 Registry 進行訂閱操作。訂閱操作會從 ZooKeeper 中取得 Provider 註冊的 URL,並在 ZooKeeper 中新增對應的監聽器。取得Provider URL 之後,Consumer 會根據負載平衡演算法從多個Provider 中選擇一個Provider 並與其建立連接,最後發起對Provider RPC 呼叫。如果Provider URL 發生變更,Consumer 將會透過先前訂閱過程中在註冊中心新增的監聽器,取得到最新的Provider URL 訊息,進行相應的調整,例如斷開與宕機Provider 的連接,並與新的Provider 建立連接。Consumer 與Provider 建立的是長連接,且Consumer 會快取Provider 訊息,所以一旦連接建立,即使註冊中心宕機,也不會影響已運行的ProviderConsumer

Monitor

監控中心。用於統計服務的呼叫次數和呼叫時間。 ProviderConsumer 在運行過程中,會在記憶體中統計呼叫次數和呼叫時間,定時每分鐘發送一次統計資料到監控中心。監控中心在上面的架構圖中並不是必要角色,監控中心宕機不會影響ProviderConsumer 以及Registry 的功能,只會遺失監控數據而已。

猥瑣發育,後期爆發,(前期可能關注的不多,但是後期它特別香)

Container:

服務運行容器。是一個獨立的容器,因為服務通常不需要TomcatJBoss等Web容器的特性,沒必要用Web容器去載入服務。服務容器只是一個簡單的main方法,並載入一個簡單的Spring容器,用於暴露服務。

流程說明

在上面這張圖中,有幾個角色,並且還畫了很多線條,下面我們對此做一個簡單說明。

  • 服務容器負責啟動,加載,運行服務提供者。
  • 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
  • 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
  • 註冊中心傳回服務提供者位址清單給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
  • 服務消費者,從提供者位址清單中,基於軟負載平衡演算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。
  • 服務消費者和提供者,在記憶體中累積呼叫次數和呼叫時間,定時每分鐘發送一次統計資料到監控中心。

Dubbo官網

#Dubbo的官網:https://dubbo .apache.org/

Dubbo源碼分析:小白入門篇

#由於Dubbo是由阿里巴巴技術團隊開發的,所以,文件方面對於咱們中國人來說那是相當的友好,一個字:爽!

另外,Dubbo官網上很多東西,我們就不在這裡一一介紹了。

建議大家都去官網逛逛。

話不多說,咱們先來嗨一把!

demo案例1

我們先來搞一個沒有註冊中心的案例。

我們建立一個項目,並建立三個module

  • #dubbo-demo
  • dubbo-demo-api
  • #dubbo-demo-provider

Dubbo源碼分析:小白入門篇

########################## #####dubbo-demo-consumer###############專案整體結構如下:########################################## #下面,我們來程式碼做一個簡單說明。 ###

首先是pom依賴:

<!--dubbo的依赖-->
<dependency>
     <groupId>org.apache.dubbo</groupId>
     <artifactId>dubbo</artifactId>
     <version>3.0.4</version>
</dependency>
<!-- provider和consumer共用类-->
<dependency>
     <groupId>com.tian.dubbo</groupId>
     <artifactId>dubbo-demo-api</artifactId>
     <version>1.0-SNAPSHOT</version>
</dependency>

consumer和provider專案都需要加入這兩個依賴。

api

api主要是定義服務介面以及一些工具類,主要是給consumer和provider共用。

在api中我們只定義了一個服務介面:DemoService

package com.tian.dubbo.service;

public interface DemoService {
    String sayHello(String msg);
}

然後打成jar,在consumer和provider專案中加入到pom.xml 依賴裡,最後兩遍都可以使用了。

provider

在resources目錄下建立一個目錄META-INF.spring,然後在目錄下建立一個application.xml,內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--Dubbo服务名称--> 
    <dubbo:application name="dubbo-provider"/>
    <!--不需要注册到服务注册中心--> 
    <dubbo:registry address="N/A"/>
    <!--端口和协议--> 
    <dubbo:protocol name="dubbo" port="20880"/>
    <!--我们的服务--> 
    <dubbo:service interface="com.tian.dubbo.service.DemoService" ref="demoService"/>
    <bean id="demoService" class="com.tian.dubbo.service.DemoServiceImpl"/>
</beans>

再在resources目錄下建立一個日誌列印的設定檔:log4j.properties

###set log levels###
log4j.rootLogger=debug, stdout
###output to the console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n

在定義一個業務實作類別:DemoServiceImpl

package com.tian.dubbo.service;

public class DemoServiceImpl implements DemoService {
    public String sayHello(String msg) {
        System.out.println("msg= " + msg);
        return "SUCCESS";
    }
}

再來就是定義一個provider的啟動類別:ProviderMain

package com.tian.dubbo;

import org.apache.dubbo.container.Main;

public class ProviderMain {
    public static void main(String[] args) {
        Main.main(args);
    }
}

注意:这里的Main类是Dubbo

最后,我们启动ProviderMain类,日志输出:

Dubbo源碼分析:小白入門篇

好了,已经启动成功了。

我们继续来看看consumer项目,在项目中,也就是调用我们服务的项目。

consumer

在consumer项目中application.xml配置文件和provider有所区别。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- 服务名称-->
    <dubbo:application name="dubbo-consumer"/>
    <!--不需要注册到服务注册中心--> 
    <!-- 通过url直接调用-->
    <dubbo:reference id="demoService"
                     interface="com.tian.dubbo.service.DemoService"
     url="dubbo://127.0.0.1:20880/com.tian.dubbo.service.DemoService"/>
</beans>

这个url地址,我们在provider启动的时候,可以从日志中找到。

日志文件和provider一样,然后就是ConsumerMain启动类了。

package com.tian.dubbo;

import com.tian.dubbo.service.DemoService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ConsumerMain {
    public static void main(String[] args) {
        DemoService demoService = null;
        ApplicationContext context = new ClassPathXmlApplicationContext
                ("classpath:META-INF/spring/application.xml");
        demoService = context.getBean(DemoService.class);
        //调用服务
        System.out.println(demoService.sayHello("tian"));
    }
}

前面,我们已经把provider成功启动了,下面我们就来启动ConsumerMain

Dubbo源碼分析:小白入門篇

从日志可以看出我们已经成功调用了provider,我们再来看看provider的日志输出:

Dubbo源碼分析:小白入門篇

也成功的输出了我们想要的。

到此,一个简单的入门无注册中心(通过url直接调用)的方式就完成了。

url在開發聯調的時候還是很擁有的哦,因為它擺脫了對註冊中心的依賴。

demo案例2

我們已經示範完了無註冊中心,下面我們來示範有註冊中心。

Dubbo目前差不多能支援市面上所有的註冊中心:

  • #consul
  • zookeeper
  • eureka
  • redis
  • etcd
  • nacos
  • ....

我們在實際開發中,Dubbo註冊中心大部分都是使用ZookeeperNacos

下面們基於Zookeeper來示範(nacos類似,下面會說到)。

程式碼層面

我基於前面的案例進行改造。改造只需要調整兩個地方:

  • consumer和provider中添加pom依赖
  • application.xml中添加注册中心
pom依赖

我们需要在前面demo中consumer和provider的pom.xml中添加Zookeeper的依赖:

<dependency>
     <groupId>org.apache.dubbo</groupId>
     <artifactId>dubbo-dependencies-zookeeper</artifactId>
     <version>3.0.4</version>
     <type>pom</type>
</dependency>
provider端

在provider项目中我们需要调整:

<dubbo:registry address="N/A"/>

改成:

<dubbo:registry address="zookeeper://127.0.0.1:2181" timeout="10000"/>

这个timeout建议配上,我这里其实没必要配,因为dubbo服务和Zookeeper都在我本地。

然后我们启动provider项目:

Dubbo源碼分析:小白入門篇

看到我们的项目已经启动成功,并且已经注册到Zookeeper上了。

我们可以使用Zookeeper的可视化工具,看看注册上去的信息。

Dubbo源碼分析:小白入門篇

我们再看看consumer端的调整。

consumer端

我们需要在application.xml中添加

<dubbo:registry address="zookeeper://127.0.0.1:2181" timeout="10000"/>

同时,去掉reference中的url:

<dubbo:reference id="demoService"
                     interface="com.tian.dubbo.service.DemoService"
     url="dubbo://127.0.0.1:20880/com.tian.dubbo.service.DemoService"/>

因为是通过Zookeeper注册中心拿到地址,所以这里的url就可以去掉了。

最后,启动ConsumerMain类:

Dubbo源碼分析:小白入門篇

可以看到我们也成功调用服务,另外也有大量的Zookeeper日志。

到此,说明,我们的Zookeeper为注册中心的demo案例也成功了。

注意:provider和consumer项目都需要依赖相关jar包(api、zookeeper、dubbo)

其他

关于Nacos,我们这里就不演示了,因为太简单了,如果你把Nacos搭建好了后,直接配置就好了。

<dubbo:registry address="nacos://127.0.0.1:8848" timeout="10000"/>

就是把address地址改一下就可以了。

Nacos 的演示,我们下一篇文章中见。

总结

本文分享了Dubbo入门案例的两个版本:无注册中心和Zookeeper注册中心。

以上是Dubbo源碼分析:小白入門篇的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Java后端技术全栈。如有侵權,請聯絡admin@php.cn刪除