Dubbo 基礎知識以及使用方法 (持續更新中)

什麼是Dubbo

Dubbo一款高性能的RPC遠程調用框架,採用TCP長連接的方式進行遠程調用,相比較HTTP來說效率要高很多

Dubbo架構

在這裏插入圖片描述

角色說明

  • Provider:服務的提供者
  • Consumer:服務的消費者
  • Registry:服務的註冊中心,可以沒有(採用消費者直連服務者的模式)
  • Monitor:提供者/消費者的監控中心,監控狀態和數據,這個也可以沒有且不會影響到Provider或Consumer
  • Contrainer:服務運行的容器,可以理解爲Spring

調用關係說明:

  1. 服務提供者啓動並創建服務在容器內
  2. 服務提供者在啓動後將服務註冊到Registry註冊中心
  3. 服務消費者在啓動後將向Registry服務註冊中心訂閱自己所需要的服務
  4. Registry服務註冊中心將把訂閱的服務提供者地址列表返回給消費者,如有變更時,將基於長連接的推送變更信息給消費者
  5. 服務消費者從服務提供者地址中根據負載均衡算法選取一臺服務器調用服務,如果服務調用失敗會再選取另一臺
  6. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心

負載均衡

在集羣負載均衡時,Dubbo 提供了多種均衡策略,缺省爲 random 隨機調用

線程模型

Dubbo的服務用兩個線程來進行服務的調用,一個是IO線程,一個是線程池的線程,通常我們在進行服務調用時,長耗時的操作,例如數據庫操作,我們會放入線程池中,這樣IO線程纔不會被阻塞,而短耗時的操作可以在IO線程種直接執行,從而減少線程的調度提高處理速度

我們可以在<protocol>dispatchthreadpool屬性來配置服務調用的派發和線程池的配置

多協議

Dubbo支持將一個服務通過多個協議暴露出來,也可以使某個服務使用dubb協議另一服務使用rmi協議這樣的方式

單服務配置多協議案例:

<!-- 多協議配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<!-- 使用dubbo協議暴露服務 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />
<!-- 使用rmi協議暴露服務 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" /> 

多服務配置多協議案例:

<!-- 多協議配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="8080" />
<!-- 使用多個協議暴露服務 -->
<dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />

多註冊中心

Dubbo支持統一服務向不同註冊中心同時註冊,或者不同服務分別註冊到不同服務上去,甚至可以同時引用註冊在不同註冊中心上的同名服務

多中心註冊案例:

 <!-- 多註冊中心配置 -->
<dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" />
<!-- 向多個註冊中心註冊 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" />

不同服務註冊不同中心案例:

<!-- 多註冊中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
<!-- 向中文站註冊中心註冊 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" />
<!-- 向國際站註冊中心註冊 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" />

多中心服務引用案例:

<!-- 多註冊中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" />
<!-- 引用中文站服務 -->
<dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" />
<!-- 引用國際站站服務 -->
<dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />

參數驗證

Dubbo支持提供者參數驗證以及消費者參數驗證

添加依賴:validation-apihibernate-validator,如果是SpringbootWeb可以不需要,因爲已經有了

  1. 使用需要的註解在bean的屬性上或者接口的參數上
// bean 屬性
@NotNull
private String name;

// 接口方法
Object validation(@NotNull ValidationParameter parameter);
Object validation(@Min(1) int id);

// 分組驗證
// 默認可按服務接口區分驗證場景,等價於參數中用到的驗證註解groups = ValidationService.class
public interface ValidationService { 
    // 使用方法分組,首字母大寫,等價於該方法用到的驗證註解groups = ValidationService.Save.class
    @interface Save{}
    void save(ValidationParameter parameter);
    // 使用默認的接口分組
    void update(ValidationParameter parameter);
}

// 關聯驗證
public interface ValidationService {   
    @GroupSequence(Update.class) // 同時驗證Update組規則
    @interface Save{}
    void save(ValidationParameter parameter);
 
    @interface Update{} 
    void update(ValidationParameter parameter);
}
  1. 配置
// 在客戶端驗證參數,消費者在調用接口服務方法時進行參數的驗證
<dubbo:reference validation="true" />

// 在服務器端驗證參數,服務提供方法被調用時進行參數的驗證
<dubbo:service validation="true" />
  1. 驗證異常信息
try{
    // .... 
}catch (RpcException e) { // 拋出的是RpcException
    // 裏面嵌了一個ConstraintViolationException
    ConstraintViolationException ve = (ConstraintViolationException) e.getCause();
    // 可以拿到一個驗證錯誤詳細信息的集合
    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations(); 
    System.out.println(violations);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章