圖解Dubbo,Dubbo服務提供者詳解

帶你聊技術發表於2023-04-19

來源:哪吒程式設計

大家好,我是哪吒。

上一篇分享了圖解Dubbo,Dubbo服務介面詳解。今天詳細的分解一下Dubbo服務提供者,實現快速入門,豐富個人簡歷,提高面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢。

三分鐘你將學會:

  1. 什麼是服務提供者
  2. 服務提供者的配置
  3. 服務提供者叢集
  4. 服務提供者的網路通訊
  5. 服務提供者的執行緒模型
  6. 服務提供者的動態配置

當今分散式系統已經成為企業中不可或缺的一部分。

在分散式系統中,服務網格是一個重要的組成部分。服務網格用於管理和排程服務,以確保系統的可用性和可擴充套件性。

其中 Dubbo 是一個流行的服務網格框架,它提供了一種簡單、可靠、高效能的方式來構建分散式系統。

在 Dubbo 中,服務提供者是框架的核心元件之一,它負責提供服務並將服務暴露給外部應用程式

本文將介紹 Dubbo 中的服務提供者,包括服務提供者的定義、服務暴露的方式、服務註冊的實現、服務提供者的容錯處理、服務提供者叢集以及服務提供者的網路通訊

一、服務提供者

Dubbo 服務提供者是指使用 Dubbo 協議提供服務的 Java 程式,它是 Dubbo 服務架構的核心部分。服務提供者透過在服務消費方和提供方之間提供 RPC(遠端過程呼叫) 服務,實現了服務之間的松耦合和低耦合。

在 Dubbo 服務架構中,服務提供者主要負責

  1. 將服務暴露給服務消費方;
  2. 並將服務消費方的請求轉化為 Dubbo 協議的請求;
  3. 然後將響應返回給服務消費方。

Dubbo服務提供者啟動流程時序圖

圖解Dubbo,Dubbo服務提供者詳解

Dubbo服務提供者關閉流程時序圖

圖解Dubbo,Dubbo服務提供者詳解

1、Dubbo服務提供者的定義

服務提供者是 Dubbo 框架的核心元件之一,它是負責提供服務的應用程式。

在 Dubbo 中,服務提供者的定義如下:

  • 服務提供者是一個 Java 類,它實現了 Dubbo 服務介面。
  • 服務提供者必須實現DubboRPC介面,該介面定義了服務呼叫的基本邏輯。
  • 服務提供者必須實現getService()方法,該方法返回服務例項的引用。

在 Dubbo 中,服務暴露的方式有兩種:廣播式服務暴露和點式服務暴露

廣播式服務暴露是指服務提供者向所有註冊的客戶端廣播服務釋出資訊,客戶端根據服務名稱和版本號等資訊自動發現服務。

點式服務暴露是指服務提供者向單個客戶端廣播服務釋出資訊,客戶端主動請求服務。

2、服務暴露的方式

在 Dubbo 服務架構中,服務提供者可以將服務暴露為 HTTP 服務、RPC 服務或者二者的結合體。

具體來說,服務提供者可以透過以下幾種方式暴露服務:

  • HTTP 服務:服務提供者可以透過 HTTP 協議提供服務,服務消費方可以透過 HTTP 請求的方式呼叫服務提供者的服務。
  • RPC 服務:服務提供者可以透過 Dubbo 協議提供 RPC 服務,服務消費方可以透過 Dubbo 協議的 RPC 請求呼叫服務提供者的服務。
  • HTTP+RPC 服務:服務提供者可以透過 HTTP 協議提供 RPC 服務,服務消費方可以透過 HTTP 請求的方式呼叫服務提供者的 RPC 服務。

Dubbo服務提供者暴露服務流程時序圖

圖解Dubbo,Dubbo服務提供者詳解

3、服務註冊的實現

Dubbo 服務註冊是指將服務提供者的資訊註冊到 Dubbo 註冊中心,讓服務消費者可以透過註冊中心查詢到服務提供者並進行呼叫。

下面是一個簡單的 Dubbo 服務註冊實現示例,基於 Apache Barrow 框架:

(1)建立服務介面

在這個示例中,我們定義了一個名為 MyService 的服務介面,它有兩個方法:hello()world()

@Service  
public interface MyService {  
    String hello() throws Exception;

    String world() throws Exception;  
}

(2)實現服務介面

在這個示例中,我們實現了 MyService 服務介面,並新增了一個 hello() 方法。

@Component  
public class MyServiceImpl implements MyService {  
    @Override  
    public String hello() throws Exception {  
        System.out.println("Hello from MyServiceImpl!");  
        return "Hello, world!";  
    }  
}

(3)註冊服務

在這個示例中,我們將 MyService 服務介面註冊到 Dubbo 註冊中心。

import org.apache.dubbo.common.URL;  
import org.apache.dubbo.common.constant.CommonConstants;  
import org.apache.dubbo.common.extension.ExtensionLoader;  
import org.apache.dubbo.common.name.NameFactory;  
import org.apache.dubbo.common.service.ServiceLoader;  
import org.apache.dubbo.registry.Registry;  
import org.apache.dubbo.registry.web.WebRegistry;

public class DubboBootstrap {

    public static void main(String[] args) throws Exception {  
        // 建立 Registry  
        Registry registry = new WebRegistry();  
        // 設定註冊中心 URL  
        URL url = URL.valueOf("dubbo://localhost:9090/my-service?registry=" + registry);  
        // 建立 NameFactory  
        NameFactory nameFactory = new NameFactory();  
        // 註冊中心配置  
        ExtensionLoader.loadExtensions(registry, "dubbo.extension.provides");  
        // 註冊服務  
        registry.bind(url, new MyService());  
        // 啟動服務  
        System.out.println("Dubbo Bootstrap started...");  
    }
}  

在這個示例中,我們首先建立了一個 WebRegistry,它使用 WebServlet 監聽埠 9090,用於向註冊中心註冊和查詢服務。然後,我們將 MyService 服務介面註冊到註冊中心。最後,我們啟動了 Dubbo 服務。

(4)服務消費者

在這個示例中,我們將建立一個服務消費者,它使用 Dubbo 註冊中心查詢服務並呼叫服務介面。

import org.apache.dubbo.common.URL;  
import org.apache.dubbo.common.constant.CommonConstants;  
import org.apache.dubbo.common.extension.ExtensionLoader;  
import org.apache.dubbo.common.name.NameFactory;  
import org.apache.dubbo.common.service.ServiceLoader;  
import org.apache.dubbo.registry.Registry;  
import org.apache.dubbo.registry.consumer.consumer.ConsumerRegistry;

public class DubboConsumer {

    public static void main(String[] args) throws Exception {  
        // 建立 Registry  
        Registry registry = new ConsumerRegistry(new HashMap<URL, Registry>());  
        // 註冊中心 URL  
        URL url = URL.valueOf("dubbo://localhost:9090/my-service?registry=" + registry);  
        // 查詢服務  
        ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);  
        for (MyService service : serviceLoader) {  
            URL serviceUrl = service.getUrl();  
            registry.bind(serviceUrl, service);  
        }  
        // 啟動服務  
        System.out.println("Dubbo Consumer started...");  
    }
}  

在這個示例中

  1. 我們建立了一個 ConsumerRegistry,它使用 HashMap 儲存註冊中心的資訊;
  2. 然後,我們將 MyService 服務介面註冊到註冊中心;
  3. 最後,我們使用 ServiceLoader 查詢服務,並將其繫結到註冊中心。

二、服務提供者的配置

1、服務提供者的XML配置

XML 配置是 Dubbo 服務架構中最常用的配置方式。服務提供者可以透過 XML 檔案來配置服務相關的資訊,如服務介面、服務實現、負載均衡、超時時間等。

XML 配置如下:

<dubbo:application name="example-service-group"  
             context="default">
  
    <dubbo:service interface="com.example.DemoService"  
                   name="demoService"  
                   version="1.0">
  
        <dubbo:argument value="com.example.DemoService"/>  
        <dubbo:method name="sayHello" args="hello"/>  
    </dubbo:service>  
    <dubbo:服務提供者 address="/>  
    <dubbo:服務提供者 address="/>  
    <dubbo:服務提供者 address="?負載均衡演算法=weight"/>  
    <dubbo:服務提供者 address="?負載均衡演算法=roundrobin"/>  
    <dubbo:服務提供者 address="?超時時間=5000"/>  
</dubbo:application>  

2、服務提供者的註解配置

註解配置是 Dubbo 服務架構中另一種常用的配置方式。服務提供者可以透過註解來配置服務相關的資訊,如服務介面、服務實現、負載均衡、超時時間等。

註解配置如下:

@ApplicationPath("path1")  
@Name("demoService")  
@Version("1.0")  
public class DemoService implements DemoService {  
    @Override  
    public String sayHello(String hello) {  
        return "Hello, " + hello + "!";  
    }  
}

3、服務提供者的容錯處理

(1)失敗重試機制

圖解Dubbo,Dubbo服務提供者詳解

解釋:

  1. 客戶端(Client)向Dubbo服務提供者(Provider)傳送請求。
  2. 如果請求成功,服務提供者將返回響應。
  3. 如果請求失敗,則Dubbo服務提供者將透過熔斷器(Circuit Breaker)返回服務熔斷響應。
  4. 如果請求過載,Dubbo服務提供者將透過熔斷器返回請求過載響應。
  5. 如果服務降級,則Dubbo服務提供者將返回服務降級響應,使用執行緒池(Thread Pool)處理請求。

(2)隔離機制

圖解Dubbo,Dubbo服務提供者詳解

Dubbo服務提供者的容錯處理的隔離機制實現了服務的隔離,當一個服務出現問題時,該服務的容錯處理機制會隔離該服務,以防止問題擴大到整個應用程式中。隔離容器可以是一個獨立的執行緒池,這個執行緒池只處理隔離的服務,以此來保護應用程式的其他部分。

(3)超時機制

在 Dubbo 服務架構中,服務提供者支援超時機制,以保障服務的響應速度和可用性。超時機制可以透過配置服務提供者的超時時間引數來實現。

下圖描述了 Dubbo 服務提供者的容錯處理的失敗超時機制的流程。在該圖中:

  1. 服務提供者首先向服務註冊中心註冊服務;
  2. 然後消費者透過服務註冊中心查詢到服務提供者列表,向服務提供者傳送請求;
  3. 服務提供者在處理請求時,如果請求超時,會返回超時響應;否則,會返回正常響應。
圖解Dubbo,Dubbo服務提供者詳解

三、服務提供者叢集

1、叢集容錯模式

(1)Failover Cluster(失敗自動切換)

Failover Cluster是Dubbo預設的叢集容錯模式,它適用於可重試的失敗場景。

在該模式下,Dubbo會自動地將呼叫失敗的請求重試到其他的服務提供者上,直到其中一個服務提供者成功返回為止。

圖解Dubbo,Dubbo服務提供者詳解

(2)Failfast Cluster(快速失敗)

Failfast Cluster適用於非冪等性的請求場景

在該模式下,Dubbo只會嘗試呼叫一次服務提供者,如果呼叫失敗則立即返回失敗結果,不會進行重試。

圖解Dubbo,Dubbo服務提供者詳解

(3)Failsafe Cluster(失敗安全)

Failsafe Cluster適用於非關鍵性請求場景

在該模式下,Dubbo會直接忽略服務提供者的異常,將異常視為服務呼叫失敗,並將失敗結果返回給呼叫方。

圖解Dubbo,Dubbo服務提供者詳解

(4)Failback Cluster(失敗自動恢復)

Failback Cluster適用於對可靠性要求較高、但不想阻塞服務呼叫的場景

在該模式下,Dubbo會將呼叫失敗的請求儲存到本地,定時重新嘗試呼叫服務提供者,直到成功返回為止。

圖解Dubbo,Dubbo服務提供者詳解

2、叢集容錯策略

在 Dubbo 服務提供者叢集中,常見的容錯策略包括如下幾種:

  • 輪詢策略:在叢集中選擇一臺伺服器作為主伺服器,其他伺服器作為從伺服器。當主伺服器出現故障時,從伺服器會自動切換到主伺服器,並繼續提供服務。
  • 負載均衡策略:在叢集中將所有服務提供者部署在不同的節點上,並透過負載均衡演算法來均衡服務提供者的負載。
  • 容錯連線策略:在叢集中將所有服務提供者部署在不同的節點上,並透過叢集間的通訊來保障叢集的穩定性和可用性。

3、叢集容錯實現

在 Dubbo 服務提供者叢集中,常用的容錯實現方式包括如下幾種:

  • 服務註冊與發現:將服務提供者部署在註冊中心上,服務消費者可以透過註冊中心來查詢服務提供者,並提供服務。
  • 服務閘道器:在服務提供者和服務消費者之間加入服務閘道器,閘道器作為服務提供者和消費者之間的介面,負責處理服務呼叫和容錯處理。
  • 訊息佇列:將服務提供者和消費者之間的通訊透過訊息佇列來實現,當服務提供者出現故障時,可以透過訊息佇列來傳遞訊息,繼續提供服務。
  • 叢集間通訊:將服務提供者部署在不同的節點上,透過叢集間通訊來保障叢集的穩定性和可用性。常用的叢集間通訊方式包括負載均衡、訊息佇列、Zookeeper 等。

四、服務提供者的網路通訊

1、Dubbo基於TCP通訊

Dubbo 是基於 TCP 通訊的,它支援多種通訊模式,包括經典模式、RPC 模式和 HTTP 模式。在經典模式下,Dubbo 使用 TCP 協議進行通訊,服務提供者和消費者之間的通訊是透過套接字進行的。在 RPC 模式下,Dubbo 使用 Dubbo 協議進行通訊,服務提供者和消費者之間的通訊也是透過套接字進行的。在 HTTP 模式下,Dubbo 使用 HTTP 協議進行通訊,服務提供者和消費者之間的通訊是透過 HTTP 請求和響應進行的。

2、通訊級別的概念

在 Dubbo 中,通訊級別指的是服務消費者和服務提供者之間的通訊級別。

具體來說,通訊級別包括如下幾個:

  • 介面級別:指服務消費者和服務提供者之間的介面級別通訊,也就是服務消費者透過介面呼叫服務提供者的方法。
  • 方法級別:指服務消費者和服務提供者之間的方法級別通訊,也就是服務消費者透過介面呼叫服務提供者的方法,服務提供者在接收到呼叫後,執行具體的服務邏輯。
  • 服務級別:指服務消費者和服務提供者之間的服務級別通訊,也就是服務消費者透過呼叫服務提供者的服務,服務提供者在接收到呼叫後,執行具體的服務邏輯。

3、通訊協議

在 Dubbo 中,服務消費者和服務提供者之間的通訊採用 Dubbo 協議進行。Dubbo 協議採用 JSON 格式進行傳輸,支援遠端呼叫和事件監聽等功能。

具體來說,Dubbo 協議包括以下內容:

  • 服務介面資訊:包括服務介面的類名、版本號、方法資訊等。
  • 服務實現資訊:包括服務實現的類名、版本號、方法資訊等。
  • 呼叫引數資訊:包括呼叫方法的引數型別、引數值等。
  • 呼叫結果資訊:包括呼叫方法的返回值型別、返回值值等。

4、Dubbo預設的序列化方式

在 Dubbo 中,預設的序列化方式為 Java 序列化。Java 序列化是一種將物件序列化為字串的序列化方式,它支援物件在記憶體中的序列化和反序列化,可以保證物件在不同平臺和不同語言之間進行傳輸和交換。但是,Java 序列化在傳輸過程中可能會出現資料丟失和變形等問題,因此需要謹慎使用。

5、序列化方式的擴充套件支援

Dubbo 提供了多種序列化方式,包括 JSON 序列化、XML 序列化、化石序列化等。服務提供者可以根據需要,自行選擇序列化方式。同時,Dubbo 還提供了序列化方式的擴充套件支援,可以自定義序列化方式,滿足不同的需求。

6、Dubbo協議的傳輸方式

Dubbo 協議採用 HTTP 協議進行傳輸,支援客戶端和伺服器之間的通訊。

具體來說,Dubbo 協議的傳輸方式包括如下幾種:

  • GET 方式:客戶端向伺服器傳送 GET 請求,伺服器返回請求結果。
  • POST 方式:客戶端向伺服器傳送 POST 請求,伺服器接收請求資料,並根據請求資料執行相應的操作。
  • PUT 方式:客戶端向伺服器傳送 PUT 請求,伺服器將請求資料儲存到伺服器中。
  • DELETE 方式:客戶端向伺服器傳送 DELETE 請求,伺服器刪除請求資料。

7、傳輸方式的擴充套件支援

Dubbo 協議的傳輸方式可以透過自定義 HTTP 客戶端和伺服器進行擴充套件支援。自定義 HTTP 客戶端和伺服器可以實現自定義的傳輸方式,滿足不同的需求。同時,Dubbo 還提供了 HTTP 傳輸方式的擴充套件支援,可以自定義 HTTP 傳輸方式,滿足不同的需求。

五、服務提供者的執行緒模型

1、什麼是執行緒模型

執行緒模型是指描述計算機程式中執行緒 (也稱為程式或例項) 如何執行的模型。在一個計算機程式中,執行緒是程式執行的基本單位。每個執行緒都有自己的堆疊、變數和執行順序,它們可以獨立地執行,直到它們被阻塞或超時為止。執行緒模型描述了執行緒如何協作、同步和通訊,以確保程式的正確性和可靠性。

2、Dubbo執行緒模型

Dubbo 執行緒模型是 Dubbo 框架中用於實現服務消費和服務提供者之間通訊的執行緒模型。在 Dubbo 中,服務消費者和服務提供者之間是透過執行緒池進行的,每個執行緒池代表一個服務消費者或服務提供者,執行緒池中的執行緒負責執行服務消費者的請求或服務提供者的服務。

3、執行緒池模型

執行緒池模型是指服務提供者在執行服務請求時使用的執行緒模型。線上程池模型中,服務提供者會建立一個或多個執行緒,用於執行服務請求。每個執行緒都擁有自己的堆疊和變數,當服務請求結束時,服務提供者會自動銷燬執行緒,釋放資源。

4、單一執行緒模型

單一執行緒模型是指服務提供者在執行服務請求時使用的執行緒模型。在單一執行緒模型中,服務提供者只會建立一個執行緒,用於執行服務請求。當服務請求結束時,服務提供者不會自動銷燬執行緒,而是等待執行緒完成任務後才會銷燬執行緒。

5、伸縮執行緒模型

伸縮執行緒模型是指服務提供者在執行服務請求時使用的執行緒模型,它可以根據實際需求自動增加或減少執行緒的數量。在伸縮執行緒模型中,服務提供者會建立多個執行緒,當服務請求數量增加時,服務提供者會自動增加執行緒的數量,以保證服務請求的及時處理。當服務請求數量減少時,服務提供者會自動減少執行緒的數量,減少資源浪費。

六、服務提供者的動態配置

1、配置方式的概述

靜態配置是指在程式碼中直接編寫服務提供者的配置資訊,例如服務介面的 IP 地址、埠號、協議、依賴庫等資訊。這種方式的優點是簡單易用,可以快速地搭建服務提供者,但是在執行時無法根據實際情況進行修改。

動態配置是指在執行時根據請求的實際情況動態地配置服務提供者。這種方式的優點是靈活性高,可以根據實際情況進行修改,但是在程式碼量上會多一些。

2、動態配置方式

Dubbo 提供了多種方式來實現動態配置,其中最常用的方式是使用 RegisterUtil.register() 方法進行註冊。在使用動態配置時,需要先建立一個 RegisterUtil 物件,然後使用該物件進行註冊。註冊完成後,可以透過呼叫 RegisterUtil.unregister() 方法來取消註冊。

另外,Dubbo 還支援使用 XML 檔案進行配置,可以使用 XML 檔案來儲存服務提供者的配置資訊。XML 檔案的格式如下:

<dubbo:service interface="com.example.demo.Service"  
       name="demoService"  
       registry-address="localhost:20888">
  
    <dubbo:reference name="demoDao" interface="com.example.demo.Dao" />  
</dubbo:service>  

在上面的 XML 檔案中,interface 屬性指定了服務介面的名稱,name 屬性指定了服務的名稱,registry-address 屬性指定了服務註冊中心的連線地址,dubbo:reference 屬性指定了服務依賴的物件。

3、配置規則

Dubbo 的配置規則主要包括以下幾個方面:

  • 服務介面的名稱空間:服務介面的名稱空間指定了服務介面的名稱空間,例如 com.example.demo.
  • 服務名稱:服務名稱指定了服務的名稱,例如 demoService.
  • 服務註冊中心:服務註冊中心指定了服務註冊的中心地址,例如 localhost:20888.
  • 服務依賴庫:服務依賴庫指定了服務依賴的其他庫,例如 com.example.demo.Dao.

4、 配置規則的實現

在實現服務提供者的配置資訊時,需要按照上述規則進行編寫。例如,下面是一個符合規則的服務提供者的配置資訊:

@Component  
public class DemoService implements Service {  
 
    @Override  
    public void run(String name, Map<String, Object> params) throws Exception {  
        System.out.println(name + " is running...");  
    }  
}

@Component  
public class DemoDao implements Dao {  
 
    @Override  
    public void doSomething(String name) throws Exception {  
        System.out.println(name + " is done.");  
    }  
}

@Configuration  
public class DemoConfig {  
 
    @Bean  
    public Service service() {  
        return new DemoService();  
    }  
 
    @Bean  
    public Dao dao() {  
        return new DemoDao();  
    }  
}

在上面的程式碼中,@Component 註解標記了 DemoServiceDemoDao 兩個元件,並且它們都實現了 Service 介面。@Configuration 註解標記了 DemoConfig 類,它包含了兩個 @Bean 註解,分別標記了 DemoServiceDemoDao 元件的注入點。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2946811/,如需轉載,請註明出處,否則將追究法律責任。

相關文章