1. 程式人生 > 程式設計 >關於Dubbo ,一些你不知道卻很好用的功能!

關於Dubbo ,一些你不知道卻很好用的功能!

dubbo功能非常完善,很多時候我們不需要重複造輪子,下面列舉一些你不一定知道,但是很好用的功能;

01 直連Provider

在開發及測試環境下,可能需要繞過註冊中心,只測試指定服務提供者,這時候可能需要點對點直連,點對點直連模式,將以服務介面為單位,忽略註冊中心的提供者列表,A 介面配置點對點,不影響 B 介面從註冊中心獲取列表(說明:官方只建議開發&測試環境使用該功能),用法如下,url指定的地址就是直連地址:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" version="1.0.0"
url="dubbo://172.18.1.205:20888/" />複製程式碼

02 多版本

當一個介面實現,出現不相容升級時,可以用版本號過渡,版本號不同的服務相互間不引用,用法如下:

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" version="1.0.0" />複製程式碼

利用dubbo該特性,我們能夠實現一些功能的灰度釋出,實現步驟如下:

  • 介面舊的實現定義version="1.0.0",介面新的實現version="2.0.0"
  • Consumer端定義version="*"

這樣定義Provider和Consumer後,新舊介面實現各承擔50%的流量;

利用dubbo該特性,還能完成不相容版本遷移:

  • 在低壓力時間段,先升級一半Provider為新版本;
  • 再將所有消費者升級為新版本;
  • 然後將剩下的一半提供者升級為新版本。

03 回聲測試

回聲測試用於檢測服務是否可用,回聲測試按照正常請求流程執行,能夠測試整個呼叫是否通暢,可用於監控。
所有服務自動實現EchoService介面,只需將任意服務引用強制轉型為EchoService 即可使用,使用方式(demoService是spring管理的bean)

EchoService echoService = (EchoService) demoService;
System.out.println(echo
Service.$echo("hello"));複製程式碼

04 隱式引數

可以通過 RpcContextsetAttachment()getAttachment() 在Consumer和Provider之間進行引數的隱式傳遞,例如Controller層攔截登入token,把根據token得到的memberId傳給dubbo服務就能使用隱式引數傳遞的方式,setAttachment()設定的 KV 對,在完成一次遠端呼叫會被清空,即多次遠端呼叫要多次設定。使用方式:

  • 服務端set
RpcContext.getContext().setAttachment("CRT_MEMBER_ID","13828886888");複製程式碼
  • 客戶端get
RpcContext.getContext().getAttachment("CRT_MEMBER_ID")複製程式碼

05 上下文

上下文中存放的是當前呼叫過程中所需的環境資訊。所有配置資訊都將轉換為 URL 的引數
RpcContext 是一個 ThreadLocal 的臨時狀態記錄器,當接收到 RPC 請求,或發起 RPC 請求時,RpcContext 的狀態
都會變化。例如:A 調 B,B 再調 C,則 B 機器上,在 B 調 C 之前,RpcContext 記錄的是 A 調 B 的資訊,在 B 調 C
之後,RpcContext 記錄的是 B 調 C 的資訊。使用方式:

boolean isConsumerSide = RpcContext.getContext().isConsumerSide();複製程式碼

06 本地偽裝

本地偽裝通常用於服務降級,例如某驗權服務,當服務提供方全部掛掉後,客戶端不丟擲異常,而是通過 Mock 資料
返回授權失敗。使用方式如下,mock指定的實現類在Provider丟擲RpcException異常時執行(一定要丟擲RpcException異常才執行),取代遠端返回結果:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" version="1.0.0" mock="com.alibaba.dubbo.demo.consumer.mock.DemoServiceMock"/>複製程式碼

DemoServiceMock實現原始碼:

public class DemoServiceMock implements DemoService {    
       public String sayHello(String name) {        
              return "mock-value";    
       }
}複製程式碼

07 泛化呼叫

泛化介面呼叫方式主要用於客戶端沒有 API 介面及模型類元的情況,引數及返回值中的所有 POJO 均用Map表示,通常用於框架整合,例如:實現一個通用的服務測試框架,可通過GenericService呼叫所有服務實現。使用方式:

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" generic="true"/>複製程式碼

呼叫原始碼:

/** 
 * @author afei 
 * @version 1.0.0 
 * @since 2017年11月22日 
 */
public class Main {     
       public static void main(String[] args) {        
              // 引⽤遠端服務,該例項⾥⾯封裝了所有與註冊中⼼及服務提供⽅連線,請快取        
              ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();        
              // 弱型別接⼝名        
              reference.setInterface("com.alibaba.dubbo.demo.DemoService");        
              reference.setVersion("1.0.0");        
              // 宣告為泛化接⼝        
              reference.setGeneric(true);        
              // ⽤com.alibaba.dubbo.rpc.service.GenericService可以替代所有介面引用⽤        
              GenericService genericService = reference.get();        
              // 基本型別以及Date,List,Map等不需要轉換,直接調⽤        
              Object result = genericService.$invoke("sayYes",new String[] {
                     "java.lang.String"
              },new Object[] {"afei"});        
              System.out.println("result --> "+result);         
              // ⽤Map表示POJO引數,如果返回值為POJO也將自動轉成Map        
              Map<String,Object> teacher = new HashMap<String,Object>();        
              teacher.put("id","1");        
              teacher.put("name","admin");        
              teacher.put("age","18");        
              teacher.put("level","3");        
              teacher.put("remark","測試");        
              // 如果返回POJO將自動轉成Map        
              result = genericService.$invoke("justTest",new String[] 
                 {"com.alibaba.dubbo.demo.bean.HighTeacher"},new Object[]{teacher});                  System.out.println("result --> "+result);    
              }
}複製程式碼

08 訪問日誌

如果想記錄每次請求資訊,可開啟訪問日誌,類似於Ngnix的訪問日誌。注意:此日誌量比較大,請注意磁碟容量。使用方式(如果配置區域性,全域性訪問日誌就會失效):
配置全域性:

<dubbo:provider accesslog="/app/dubbo-demo.log"/>複製程式碼

配置區域性:

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" accesslog="/app/demo.log"/>  <dubbo:service interface="com.alibaba.dubbo.demo.TestService" ref="testService" accesslog="/app/test.log"/>複製程式碼

日誌格式樣式:

[2017-11-22 10:23:20] 172.18.1.205:56144 -> 172.18.1.205:20886 - com.alibaba.dubbo.demo.DemoService:1.0.0 sayHello(java.lang.String) ["afei"]複製程式碼

09 延遲暴露

如果服務需要預熱時間,比如初始化本地快取,等待相關資源就位等,可以使用delay進行延遲暴露。使Dubbo在Spring容器初始化完後延遲多少毫秒再暴露服務。使用方式:

<dubbo:provider delay="5000"/>複製程式碼

或者:

<dubbo:service delay="5000" interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" version="1.0.0"/>複製程式碼