本地偽裝
功能描述
Dubbo3 中有一種機制可以實現輕量級服務降級,即本地偽裝1。
使用場景
本地偽裝通常用於服務降級。例如,對於驗證服務,當所有服務提供者都掛斷時,如果服務消費者此時發起遠端呼叫,則呼叫將失敗並拋出 RpcException
。
為了避免這種直接拋出異常的情況,客戶端可以使用本地偽裝來提供 Mock 資料並返回授權失敗。
使用方法
啟用 Mock 配置
在 Spring XML 配置檔案中以下列方式配置
<dubbo:reference interface="com.foo.BarService" mock="true" />
或
<dubbo:reference interface="com.foo.BarService" mock="com.foo.BarServiceMock" />
在專案中提供 Mock 實現2
package com.foo;
public class BarServiceMock implements BarService {
public String sayHello(String name) {
// You can fake fault-tolerant data, this method is only executed when RpcException occurs
return "fault tolerance data";
}
}
使用 return 關鍵字模擬返回值
使用 return
返回一個由字串表示的物件作為 Mock 的返回值。合法的字串可以是
- 空:代表空,返回基本類型的預設值、集合類的空值以及自訂實體類的空物件3
- null:返回
null
- true:返回
true
- false:返回
false
- JSON 字串:返回 JSON 字串反序列化後獲得的物件
例如,如果服務的消費者經常需要使用 try-catch 來捕捉異常,例如
public class DemoService {
public Offer findOffer(String offerId) {
Offer offer = null;
try {
offer = offerService. findOffer(offerId);
} catch (RpcException e) {
logger. error(e);
}
return offer;
}
}
那麼可以考慮改為 Mock 實現,並在 Mock 實現中 return null
。如果只是想簡單地忽略異常,則在 2.0.11
及以上版本中可以使用
<dubbo:reference interface="com.foo.BarService" mock="return null" />
使用 throw 關鍵字 Mock 拋出異常
使用 throw
返回一個 Exception 物件作為 Mock 的返回值。
當呼叫失敗時,會拋出預設的 RPCException。
<dubbo:reference interface="com.foo.BarService" mock="throw"/>
當呼叫中發生錯誤時,拋出指定的 Exception4
<dubbo:reference interface="com.foo.BarService" mock="throw com.foo.MockException"/>
使用 force 和 fail 關鍵字來配置 Mock 的行為。
force:
表示強制使用 Mock 行為,在這種情況下不會進行遠端呼叫。
fail:
與預設行為一致,僅在遠端呼叫發生錯誤時才使用 mock 行為。也就是說,配置時實際上可以不使用 fail
關鍵字,而直接使用 throw
或 return
。
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"/>
當呼叫失敗時,返回指定的值。
<dubbo:reference interface="com.foo.BarService" mock="fail:return fake"/>
<!-- Equivalent to the following writing -->
<dubbo:reference interface="com.foo.BarService" mock="return fake"/>
當呼叫失敗時,拋出異常。
<dubbo:reference interface="com.foo.BarService" mock="fail:throw com.foo.MockException"/>
<!-- Equivalent to the following writing -->
<dubbo:reference interface="com.foo.BarService" mock="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>
注意事項
Mock 是 Stub 的一個子集,方便服務提供者在客戶端實現容錯邏輯。因為通常需要在發生 RpcException(例如網路故障、逾時等)時執行容錯,而在發生業務異常(例如登入錯誤的使用者名稱和密碼)時不需要容錯。如果使用 Stub,您可能需要捕捉並依賴 RpcException 類別,但使用 Mock 可以不依賴 RpcException,因為它的約定是僅在發生 RpcException 時才執行。 ↩︎
在介面旁邊放置一個 Mock 實作,該實作實現 BarService 介面並具有無參數建構子。同時,如果設定檔中未明確指定 Mock 類別,則需要確保 Mock 類別的完整類別名稱的格式為「原始完整類別名稱 + Mock」,例如
com.foo.BarServiceMock
,否則 Mock 將會失敗。 ↩︎如果返回值是一個實體類別,則它將返回一個具有預設值的空物件,而不是
null
。 ↩︎自訂異常必須具有一個以
String
作為輸入參數的建構子,該建構子將用於接收異常資訊。 ↩︎