Dubbo特性之本地存根、本地僞裝和隱式參數傳遞

本地存根

  • 本地存根類似於Dubbo的靜態代理。
  • dubbo會在客戶端生成一個代理。
  • stub必須有可傳入Proxy的函數。
    在這裏插入圖片描述
    遠程服務後,客戶端通常只剩下接口,而實現全在服務端,但提供方有些時候想在客戶端也執行部分邏輯,比如:做ThreadLocal緩存,提前驗證參數,調用失敗後僞造容錯數據等等,此時就需要在API中帶上Stub,客戶端生成Proxy實例,會把Proxy通過構造函數傳給stub, 然後把Stub暴露給用戶,stub可以決定要不要去調Proxy。

在spring配置文件中按以下方式配置:

<dubbo:service interface="com.foo.BarService" stub="true" />

<dubbo:service interface="com.foo.BarService" stub="com.foo.BarServiceStub" />

提供Stub的實現,在interface旁邊放一個Stub的實現,它實現BarService接口,並有一個傳入遠程BarService實例的構造函數。

package com.foo;
public class BarServiceStub implements BarService {
    private final BarService barService;
    
    // 構造函數傳入真正的遠程代理對象
    public BarServiceStub(BarService barService){
        this.barService = barService;
    }
 
    public String sayHello(String name) {
        // 此代碼在客戶端執行, 你可以在客戶端做ThreadLocal本地緩存,或預先驗證參數是否合法,等等
        try {
            return barService.sayHello(name);
        } catch (Exception e) {
            // 你可以容錯,可以做任何AOP攔截事項
            return "容錯數據";
        }
    }
}

本地僞裝

  • 本地僞裝是本地存根的一個子集。
  • 通常會使用本地僞裝處理服務降級。
  • 建議本地僞裝在客戶端實現。

本地僞裝通常用於服務降級,比如某驗權服務,當服務提供方全部掛掉後,客戶端不拋出異常,而是通過Mock數據返回授權失敗。Mock只能捕獲RpcException 類。

在 spring 配置文件中按以下方式配置:


<dubbo:reference interface=“com.foo.BarService” mock=“true” />


<dubbo:reference interface="com.foo.BarService" mock="com.foo.BarServiceMock" />

在工程中提供 Mock 實現 , 在interface旁邊放一個Mock實現,它實現BarService接口,並有一個無參構造函數。

package com.foo;
public class BarServiceMock implements BarService {
    public String sayHello(String name) {
        // 你可以僞造容錯數據,此方法只在出現RpcException時被執行
        return "容錯數據";
    }
}

如果服務的消費方經常需要 try-catch 捕獲異常,如:

Offer offer = null;
try {
    offer = offerService.findOffer(offerId);
} catch (RpcException e) {
   logger.error(e);
}

請考慮改爲 Mock 實現,並在 Mock 實現中 return null。如果只是想簡單的忽略異常,在 2.0.11 以上版本可用:

<dubbo:reference interface="com.foo.BarService" mock="return null" />

進階用法

return

使用return來返回一個字符串表示的對象,作爲Mock的返回值。合法的字符串可以是:

  • empty: 代表空,基本類型的默認值,或者集合類的空值
  • null: null
  • true: true
  • false: false
  • JSON 格式: 反序列化 JSON 所得到的對象
throw

使用 throw 來返回一個 Exception 對象,作爲 Mock 的返回值。

當調用出錯時,拋出一個默認的 RPCException:

<dubbo:reference interface="com.foo.BarService" mock="throw" />

當調用出錯時,拋出指定的 Exception:

<dubbo:reference interface="com.foo.BarService" mock="throw com.foo.MockException" />
force 和 fail

在 2.6.6 以上的版本,可以開始在 Spring XML 配置文件中使用 fail: 和 force:。force: 代表強制使用 Mock 行爲,在這種情況下不會走遠程調用。fail: 與默認行爲一致,只有當遠程調用發生錯誤時才使用 Mock 行爲。force: 和 fail: 都支持與 throw 或者 return 組合使用。

強制返回指定值:

<dubbo:reference interface="com.foo.BarService" mock="force:return fake" />

強制拋出指定異常:

<dubbo:reference interface="com.foo.BarService" mock="force:throw com.foo.MockException" />
在方法級別配置 Mock

Mock 可以在方法級別上指定,假定 com.foo.BarService 上有好幾個方法,我們可以單獨爲 sayHello() 方法指定 Mock 行爲。具體配置如下所示,在本例中,只要 sayHello() 被調用到時,強制返回 “fake”:

<dubbo:reference id="demoService" check="false" interface="com.foo.BarService">
    <dubbo:parameter key="sayHello.mock" value="force:return fake"/>
</dubbo:reference>

隱式參數

可以通過RpcContext 上的setAttachmentgetAttachment在這裏插入代碼片在服務消費方和提供方之間進行參數的隱式傳遞。
在這裏插入圖片描述

在服務消費方端設置隱式參數

setAttachment 設置的 KV 對,在完成下面一次遠程調用會被清空,即多次遠程調用要多次設置。

RpcContext.getContext().setAttachment("index", "1"); // 隱式傳參,後面的遠程調用都會隱式將這些參數發送到服務器端,類似cookie,用於框架集成,不建議常規業務使用
xxxService.xxx(); // 遠程調用
// ...
在服務提供方端獲取隱式參數
public class XxxServiceImpl implements XxxService {
 
    public void xxx() {
        // 獲取客戶端隱式傳入的參數,用於框架集成,不建議常規業務使用
        String index = RpcContext.getContext().getAttachment("index"); 
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章