Dubbo學習筆記

小野居大王發表於2020-10-26
Dubbo

Dubbo學習內容

​ Dubbo發展背景

​ Dubbo概述

​ RPC

​ Zookeeper、Dubbo控制檯的安裝

​ Dubbo入門例子

​ Dubbo詳細講解

​ Dubbo整合spring mvc

​ Dubbo整合springboot


Dubbo發音:|ˈdʌbəʊ|

Dubbo官方網站:http://dubbo.apache.org/

Dubbo是阿里巴巴開發的,已經貢獻給Apache,並且已經成Apache的頂級開源專案

1. Dubbo的發展背景

​ 文件:http://dubbo.apache.org/zh-cn/docs/user/preface/background.html

​ 隨著網際網路的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分散式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。

在這裡插入圖片描述

1.1 單一應用架構

​ 當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。

​ 此時,用於簡化增刪改查工作量的資料訪問框架(ORM)是關鍵。

​ 使用一個web容器(如tomcat),然後使用Servlet/JSP技術,最後選擇一個合適資料庫管理系統來儲存資料(MySQL、Oracle)。

1.2 垂直應用架構

​ 當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,提升效率的方法之一是將應用拆成互不相干的幾個應用,以提升效率。

​ 此時,用於加速前端頁面開發的Web框架(MVC)是關鍵。

​ 使用者系統、許可權系統、商品系統、訂單系統、物流系統…

特點:系統獨立部署,每一個系統都有完整的前後端;

問題:各個系統無法做到完全獨立,公共模組無法複用,系統之間通訊比較麻煩;

1.3 分散式服務架構

​ 當垂直應用越來越多,應用之間互動不可避免,這時將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。

​ 此時,用於提高業務複用及整合的分散式服務框架(RPC)是關鍵。

分散式架構的難點

  1. 各個系統如何進行遠端呼叫
  2. 如何進行業務拆分

1.4 流動計算架構

​ 當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個排程中心基於訪問壓力實時管理叢集容量,提高叢集利用率。此時,用於提高機器利用率的資源排程和治理中心(SOA)是關鍵。

2. RPC

​ RPC(Remote Procedure Call)- 遠端過程呼叫,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層的網路技術協議。RPC假定某種傳輸協議的存在(如TCP),為通訊程式攜帶資料;

​ 通俗的說,RPC可以讓我們像呼叫本地方法一樣呼叫遠端計算機提供的服務;

2.1 RPC的簡單原理

在這裡插入圖片描述

1. 客戶端以本地呼叫的方式呼叫遠端服務
2. client stub接收到呼叫後,將方法、引數等組裝成能夠進行網路傳輸的訊息;
3. client stub查詢服務地址,找到之後,將訊息傳送到服務端;
4. server stub收到訊息之後,對收到的訊息進行解碼;
5. server stub根據解碼結果,使用反射的方式呼叫本地服務;
6. 服務端執行完成之後將結果返回給Server stub;
7. server stub將返回結果打包成訊息併傳送給客戶端;
8. client stub收到訊息後,對結果進行解碼;

總結: 實現RPC的三個技術點

  • 服務定址
  • 網路連線
  • 資料的序列化

3. Dubbo

3.1 Dubbo是什麼

​ Apache Dubbo™ 是一款高效能Java RPC框架

​ Apache Dubbo |ˈdʌbəʊ| 是一款高效能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向介面的遠端方法呼叫智慧容錯和負載均衡,以及服務自動註冊和發現

3.2 Dubbo作者

在這裡插入圖片描述

​ 從左至右:劉超,樑飛,閭剛,陳雷,劉昊旻,李鼎

3.3 Dubbo的發展歷程

​ 2008年阿里內部開始使用;
​ 2009年初,釋出1.0版本;
​ 2010年初,釋出2.0版本;
​ 2011年10月27日,阿里將Dubbo開源,版本號為2.0.7;
​ 2012年3月,釋出2.1.0版本;
​ 2014年10月,釋出2.3.11版本,之後版本停滯;
​ 2017年9月,阿里重啟維護,重點升級了依賴的JDK版本,釋出2.5.4/2.5.5版本;
​ 2017年10月,釋出2.5.6版本;
​ 2017年11月,釋出2.5.7版本,後期整合了SpringBoot;
​ 2014年10月的時候,噹噹網Fork了Dubbo原始碼,在此基礎上增加了HTTP REST協議,釋出版本號2.8.0,名字叫DubboX;
​ 網易考拉在Dubbo基礎上開發了DubboK;

3.4 Dubbo架構

  1. 架構中的角色

    Provider:服務提供者
    Consumer:服務消費者
    Registry:服務註冊和發現的中心
    Monitor:監控中心,用於統計服務呼叫情況
    Container:Dubbo容器

在這裡插入圖片描述

  1. 呼叫關係

    0、容器負責啟動、載入、執行服務提供者、消費者;

    1、服務提供者在啟動時,向註冊中心註冊自己提供的服務;

    2、服務消費者在啟動時,向註冊中心訂閱自己需要的服務;

    3、註冊中心返回服務提供者的地址列表給消費者;

    ​ 如果有服務變更(服務的上線或下線),註冊中心會基於長連線的方式推送變更給消費者;

    4、服務消費者從地址列表中,基於軟體負載均衡演算法,選擇一個服務提供者進行呼叫,如果呼叫失敗,可以重試其它提供者;

    5、服務消費者和提供者,在記憶體中累計呼叫時間和呼叫次數,每分鐘向監控中心傳送一次統計資料;

4. 安裝單機Zookeeper

4.1 windows版本

  1. 解壓zookeeper-3.4.12.tar.gz到當前目錄

  2. 在zookeeper-3.4.12目錄下建立data目錄

在這裡插入圖片描述

  1. zookeeper-3.4.12/conf目錄下的zoo_sample.cfg檔案重新命名為zoo.cfg

在這裡插入圖片描述

  1. 修改zoo.cfg檔案中的dataDir選項

在這裡插入圖片描述

  1. 啟動zookeeper服務端

    雙擊zookeeper-3.4.12/bin/zkServer.cmd

  2. 啟動zookeeper的客戶端

    雙擊zookeeper-3.4.12/bin/zkCli.cmd

4.2 Linux安裝

  1. 將zookeeper-3.4.12.tar.gz上傳到centos的/opt目錄下

  2. 解壓zookeeper-3.4.12.tar.gz到當前資料夾下(即/opt)

    tar -zxf zookeeper-3.4.12.tar.gz -C /opt
    
  3. 進入zookeeper-3.4.12,建立一個data目錄

    cd zookeeper-3.4.12
    mkdir data
    
  4. 進入zookeeper-3.4.12/conf目錄,將zoo_sample.cfg修改zoo.cfg

    cd conf
    mv zoo_sample.cfg zoo.cfg
    
  5. 編輯zoo.cfg檔案

    # 將dataDir修改為../data
    dataDir=../data
    
  6. 啟動ZK server

    cd bin
    ./zkServer.sh start
    
  7. 啟動ZK客戶端

    ./zkCli.sh
    

5. Dubbo控制檯安裝

  1. Dubbo主要用於服務治理

  2. 可以通過控制檯檢視所有服務(提供者、消費者)

  3. 可以設定負載均衡、權重調節、服務降級策略等

​ Dubbo控制檯預設訪問地址:http://localhost:7001

​ Dubbo預設的使用者名稱/密碼:root/root

​ 在dubbo-admin.jar所在目錄執行 java -jar dubbo-admin.jar即可(命令列執行)

在這裡插入圖片描述

6. Dubbo入門工程 - Hello World

  1. maven依賴

     <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>dubbo</artifactId>
         <version>2.6.5</version>
     </dependency>
     <dependency>
         <groupId>org.apache.curator</groupId>
         <artifactId>curator-framework</artifactId>
         <version>2.13.0</version>
     </dependency>
    
  2. 工程搭建 - maven聚合工程

    dubbo-hello
    dubbo-hello-interface
    dubbo-hello-provider
    dubbo-hello-consumer
    
  3. 步驟

    1. 在interface工程建立服務介面
    2. 在provider工程實現介面
    3. 在provider工程釋出服務
    4. 在consumer工程中引用
    5. 在consumer工程中呼叫遠端服務

Demo

  1. 首先建立一個聚合工程
    其中consumer與provider都需要依賴interface
    在這裡插入圖片描述

  2. 在interface工程建立服務介面 HelloService

    public interface HelloService {
    	String hello (String name);
    }
    
  3. 在provider工程實現介面 HelloServiceImpl

    public class HelloServiceImpl implements HelloService {
          @Override
          public String hello(String name) {
              System.out.println("hello invoke!");
              return "hello" + name;
          }
      }
    
  4. 在provider工程釋出服務
    provider.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://dubbo.apache.org/schema/dubbo"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
          http://dubbo.apache.org/schema/dubbo
          http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
      
          <!--1.應用名稱-->
          <dubbo:application name="hello-service"/>
          <!--2.註冊中心:把dubbo服務註冊到註冊中心-->
          <dubbo:registry address="zookeeper://127.0.0.1:2181" />
          <!--3.使用dubbo協議在20880埠號釋出服務-->
          <dubbo:protocol name="dubbo" port="20880" />
          <!--4.暴露服務-->
          <dubbo:service ref="helloService"  interface="com.service.HelloService">
          </dubbo:service>
          <!--5.配置服務實現-->
          <bean id="helloService" class="com.service.impl.HelloServiceImpl" />
      </beans>
    

ProviderTest

public class ProviderTest {
    public static void main(String[] args) throws IOException {
        new ClassPathXmlApplicationContext("provider.xml");
        System.in.read();
    }
}
  1. 在consumer工程中引用
    consumer.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://dubbo.apache.org/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 http://dubbo.apache.org/schema/dubbo
 http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

 <!--1.應用名稱-->
 <dubbo:application name="hello-consumer"/>
 <!--2.配置註冊中心-->
 <dubbo:registry address="zookeeper://127.0.0.1:2181"  />
 <!--3.引用服務-->
 <!--建立了HelloService的代理物件 並註冊成BEAN-->
 <dubbo:reference id="helloService" interface="com.etoak.service.HelloService">
 </dubbo:reference>

</beans>
  1. 在consumer工程中呼叫遠端服務
    ConsumerTest
  public class ConsumerTest {
   public static void main(String[] args) throws IOException {
       ApplicationContext ioc = new ClassPathXmlApplicationContext("consumer.xml");
       //獲取遠端服務HelloService的代理物件
       HelloService helloService = ioc.getBean(HelloService.class);
       //呼叫遠端服務
       String result = helloService.hello("Dubbo");
       System.out.println(result);

       System.in.read();
   }
}

7. Dubbo詳解

7.1 Dubbo的註冊中心有哪些

1、Multicast註冊中心

​ Multicast註冊中心不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。

2、Zookeeper註冊中心

Zookeeper 是 Apache Hadoop 的子專案,是一個樹型的目錄服務,支援變更推送,適合作為 Dubbo 服務的註冊中心,工業強度較高,可用於生產環境,並推薦使用。

3、Redis註冊中心

4、Simple 註冊中心

5、Nacos註冊中心

推薦使用 zookeeper註冊中心

7.2 Dubbo支援的協議

dubbo、rmi、hessian、http、webservice、rest、thrift、memcached、redis、grpc

推薦使用 Dubbo 協議

7.3 Dubbo服務在ZK中的儲存結構

在這裡插入圖片描述

7.4 啟動時檢查

​ Dubbo預設情況下會在啟動時檢查依賴的服務是否可用,不可用時會丟擲異常,阻止 Spring 初始化完成,以便上線時,能及早發現問題,預設 check="true"

7.4.1 關閉單個服務的啟動檢查 - 消費方

​ 可以通過<dubbo:reference check="false"> 關閉檢查,比如,測試時,有些服務不關心,或者出現了迴圈依賴,必須有一方先啟動;

<dubbo:reference id="helloService" check="false"
  interface="com.etoak.service.HelloService">
</dubbo:reference>

7.4.2 關閉所有服務的啟動檢查 - 消費方

<dubbo:consumer check="false" />

7.4.1 關閉註冊中的啟動檢查 - 消費方和提供方

<dubbo:registry address="zookeeper://127.0.0.1:2181" 
                check="false" />

7.5 配置載入流程

文件地址

​ 此篇文件主要講在應用啟動階段,Dubbo框架如何將所需要的配置採集起來(包括應用配置、註冊中心配置、服務配置等),以完成服務的暴露和引用流程。

7.5.1 配置來源

  • JVM System Properties,-D引數

  • Externalized Configuration,外部化配置

  • ServiceConfig、ReferenceConfig等程式設計介面採集的配置、spring配置

  • 本地配置檔案dubbo.properties(寫在src/main/resources)

    配置在classpath根目錄

7.5.2 配置流程

配置載入的優先順序

jvm引數 > 外部化配置 > 程式設計介面、spring配置 > dubbo.properties

Idea中配置jvm引數

在這裡插入圖片描述

7.6 XML配置 - 不同粒度配置的覆蓋關係

  • 方法級優先,介面級次之,全域性配置再次之。
  • 如果級別一樣,則消費方優先,提供方次之。
  1. 配置級別

    方法級:<dubbo:method>

    介面級:<dubbo:service><dubbo:reference>

    全域性級:<dubbo:provider><dubbo:consumer>

  2. 配置優先順序

在這裡插入圖片描述

7.7 直連提供者

​ 在開發及測試環境下,經常需要繞過註冊中心,只測試指定服務提供者,這時候可能需要點對點直連;點對點直連方式,以服務介面為單位,忽略註冊中心的提供者列表,A 介面配置點對點,不影響 B 介面從註冊中心獲取列表。

<dubbo:reference id="helloService"
                 url="dubbo://127.0.0.1:20880"
                 interface="com.etoak.service.HelloService">
  <dubbo:method name="hello" />
</dubbo:reference>

7.8 本地存根

​ 提供方有些時候想在客戶端也執行部分邏輯,比如:做 ThreadLocal 快取,提前驗證引數,呼叫失敗後偽造容錯資料等等。

實現步驟

  1. 在服務介面旁邊寫一個名字為介面名Stub的服務實現類

  2. 在這個實現類中新增一個有參的構造方法,構造方法引數就是這個服務介面的代理(也就是可以直接寫這個服務介面)

  3. 配置服務

    <!--這種方式的配置需要命名十分規範 會去找相同資料夾下的serviceNameStub
    	 即:com.etoak.service.HelloServiceStub-->
    <dubbo:service interface="com.service.HelloService"
    stub="true" />
    
    <!-- 直接指定stub方式 -->
    <dubbo:service interface="com.service.HelloService"
    stub="com.etoak.service.HelloServiceStub" />
    
  4. Demo

        /**
      * 這個程式碼是由提供者邊寫  消費者執行
      */
     public class HelloServiceStub implements HelloService{
     
         HelloService helloService;
         //構造方法引數:是真正的遠端代理物件
         public HelloServiceStub(HelloService helloService){
             this.helloService = helloService;
         }
         @Override
         public String hello(String name) {
             System.out.println("這行程式碼在客戶端(消費方)執行");
             //如果name不為空
             if(name != null && ! "".equals(name)){
                 //發起遠端呼叫
                 return helloService.hello(name);
             }
             //如果為空 則不發起遠端呼叫
             return "引數異常";
         }
     }
    

7.9 服務分組

​ 當一個介面有多種實現時,可以用 group 區分。

  1. 提供方配置

    <dubbo:service ref="helloService"
                   group="service"
                   interface="com.etoak.service.HelloService">
      <dubbo:method name="hello" timeout="4000" />
    </dubbo:service>
    <bean id="helloService"
          class="com.etoak.service.impl.HelloServiceImpl" />
    
    
    <dubbo:service ref="helloService2" 
                   group="service2"
                   interface="com.etoak.service.HelloService">
    </dubbo:service>
    <bean id="helloService2" 
          class="com.etoak.service.impl.HelloService2" />
    
    
  2. 消費方配置

    <dubbo:reference id="helloService"
                group="service2"
    				interface="com.etoak.service.HelloService">
      <dubbo:method name="hello" />
    </dubbo:reference>
    

7.10 服務的多版本

​ 當一個介面實現出現不相容需要升級時,可以用版本號過渡,版本號不同的服務相互間不引用。

可以按照以下的步驟進行版本遷移:

  1. 在低壓力時間段,先升級一半提供者為新版本
  2. 再將所有消費者升級為新版本
  3. 然後將剩下的一半提供者升級為新版本

服務端配置方式

<dubbo:service ref="helloService" stub="true"
               timeout="6000" retries="5"
               version="1.0"
               interface="com.etoak.service.HelloService">
</dubbo:service>

消費端配置

<dubbo:reference id="helloService"
                 timeout="5500"
                 version="2.0"
                 interface="com.etoak.service.HelloService">
</dubbo:reference>

7.11 負載均衡

​ Dubbo 提供了多種均衡策略,預設為 random 隨機呼叫。

1. Random LoadBalance
隨機,按權重設定隨機概率。
在一個截面上碰撞的概率高,但呼叫量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。

2. RoundRobin LoadBalance
輪詢,按公約後的權重設定輪詢比率。
存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。

3. LeastActive LoadBalance
最少活躍呼叫數,相同活躍數的隨機,活躍數指呼叫前後計數差
使慢的提供者收到更少請求,因為越慢的提供者的呼叫前後計數差會越大。

4. ConsistentHash LoadBalance
一致性 Hash,相同引數的請求總是發到同一提供者
當某一臺提供者當機時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
演算法參見:http://en.wikipedia.org/wiki/Consistent_hashing
預設只對第一個引數 Hash,如果要修改,請配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />
預設用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key=“hash.nodes” value=“320” />

控制檯配置

在這裡插入圖片描述

7.12 服務降級

​ 可以通過服務降級功能臨時遮蔽某個出錯的非關鍵服務,並定義降級後的返回策略。

  • mock=force:return+null 表示消費方對該服務的方法呼叫都直接返回 null 值,不發起遠端呼叫。用來遮蔽不重要服務不可用時對呼叫方的影響。
  • 還可以改為 mock=fail:return+null 表示消費方對該服務的方法呼叫失敗後,再返回 null 值,不拋異常。用來容忍不重要服務不穩定時對呼叫方的影響。

8. Dubbo整合springboot

​ 使用者服務 - 根據id查詢使用者資訊

  1. 建立工程

    dubbo-boot
    dubbo-boot-bean        java bean
    dubbo-boot-interface   服務介面
    dubbo-boot-mapper      mapper介面 + sql
    dubbo-boot-user-service  服務實現  springboot
    dubbo-boot-consumer      消費者    springboot
    
  2. 編寫步驟

    1. 在bean工程建立User,要實現序列化介面

    2. 在mapper工程中建立UserMapper介面、sql

    3. 在interface工程定義服務介面UserService

    4. 在user-service工程編寫服務實現

      整合mybatis、dubbo

    5. 在consumer工程引用UserService服務

      整合dubbo

    6. 啟動springboot測試

      先啟動註冊中心

      再啟動服務提供者

      再啟動消費者

Demo

待續…

相關文章