1. 程式人生 > >Dubbo - 配置示例使用詳解

Dubbo - 配置示例使用詳解

檢視Dubbo完整配置示例,參考官方文件

【1】啟動時檢查

Dubbo 預設會在啟動時檢查依賴的服務是否可用,不可用時會丟擲異常,阻止 Spring 初始化完成,以便上線時,能及早發現問題,預設 check=“true”。

可以通過 check=“false” 關閉檢查,比如,測試時,有些服務不關心,或者出現了迴圈依賴,必須有一方先啟動。

另外,如果你的 Spring 容器是懶載入的,或者通過 API 程式設計延遲引用服務,請關閉 check,否則服務臨時不可用時,會丟擲異常,拿到 null 引用,如果 check=“false”,總是會返回引用,當服務恢復時,能自動連上。

① 通過 spring 配置檔案

關閉某個服務的啟動時檢查 (沒有提供者時報錯):

<dubbo:reference interface="com.foo.BarService" check="false" />

關閉所有服務的啟動時檢查 (沒有提供者時報錯):

<dubbo:consumer check="false" />

關閉註冊中心啟動時檢查 (註冊訂閱失敗時報錯):

<dubbo:registry check="false" />

② 通過 dubbo.properties

dubbo.reference.com.foo.BarService.check=false
dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false

③ 通過 -D 引數

java -Ddubbo.reference.com.foo.BarService.check=false
java -Ddubbo.reference.check=false
java -Ddubbo.consumer.check=false 
java -Ddubbo.registry.check=false

④ 配置的含義

dubbo.reference.check=false,強制改變所有 reference 的 check 值,就算配置中有宣告,也會被覆蓋。如<dubbo:reference interface="com.foo.BarService" check="true" />

雖然設定了true,同樣按照false處理。

dubbo.consumer.check=false,是設定 check 的預設值,如果配置中有顯式的宣告,如:<dubbo:reference interface="com.foo.BarService" check="true" />,則不會受影響。那些沒有顯示設定check的reference 將會受到影響。

dubbo.registry.check=false,前面兩個都是指訂閱成功,但提供者列表是否為空是否報錯,如果註冊訂閱失敗時,也允許啟動,需使用此選項,將在後臺定時重試。


⑤ Dubbo的配置

Dubbo的配置有xml配置、屬性配置、API配置和註解配置。XML配置和註解配置就是常規專案中用到的兩種方式,一種是完全使用xml,如傳統專案;一種似乎使用註解代替,如SpringBoot。詳情參考官方文件

這裡說一下屬性配置,如上面看到的①②③。

如果公共配置很簡單,沒有多註冊中心,多協議等情況,或者想多個 Spring 容器想共享配置,可以使用 dubbo.properties 作為預設配置。

Dubbo 將自動載入 classpath 根目錄下的 dubbo.properties,可以通過JVM啟動引數-Ddubbo.properties.file=xxx.properties 改變預設配置位置。

覆蓋策略
在這裡插入圖片描述
JVM 啟動 -D 引數優先,這樣可以使使用者在部署和啟動時進行引數重寫,比如在啟動時需改變協議的埠。

XML 次之,如果在 XML 中有配置,則 dubbo.properties 中的相應配置項無效。

Properties 最後,相當於預設值,只有 XML 沒有配置時,dubbo.properties 的相應配置項才會生效,通常用於共享公共配置,比如應用名。


【2】服務呼叫超時設定和重試次數

① 超時timeout屬性設定

當呼叫一個服務長時間得不到響應的時候,並不會讓其一直阻塞等待下去。大量執行緒阻塞等待響應會引起效能下降,這時就需要設定超時屬性-timeout。

dubbo:reference的timeout屬性預設使用<dubbo:consumer>的timeout屬性,而後者的timeout屬性預設值為1000。參考schema配置參考手冊

服務消費者配置例項如下:

<dubbo:reference interface="com.web.gmall.service.UserService" 
		id="userService" timeout="5000" >
		<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:reference>

<!-- 配置當前消費者的統一規則:所有的服務都不檢查 -->
<dubbo:consumer check="false" timeout="5000"></dubbo:consumer>

服務提供者配置例項如下:

<!-- 暴露服務   ref:指向服務的真正的實現物件 -->
<dubbo:service interface="com.web.gmall.service.UserService" 
	ref="userServiceImpl" timeout="1000" >
	<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service>
	
<!--統一設定服務提供方的規則  -->
<dubbo:provider timeout="1000"></dubbo:provider>

這時候就有有個問題,哪個配置的timeout屬性生效?

在官方文件xml配置中,說明了該問題。


② xml配置覆蓋關係

以 timeout 為例,顯示了配置的查詢順序,其它 retries, loadbalance, actives 等類似:

  • 方法級優先,介面級次之,全域性配置再次之。
  • 如果級別一樣,則消費方優先,提供方次之。

其中,服務提供方配置,通過 URL 經由註冊中心傳遞給消費方。

在這裡插入圖片描述
建議由服務提供方設定超時,因為一個方法需要執行多長時間,服務提供方更清楚,如果一個消費方同時引用多個服務,就不需要關心每個服務的超時設定。

理論上 ReferenceConfig 的非服務標識配置,在 ConsumerConfig,ServiceConfig, ProviderConfig 均可以預設配置。


③ 重試次數retries屬性

為了提高可用性和冗錯率,可以設定retries屬性。dubbo:reference的retries屬性預設使用<dubbo:consumer>的retries屬性。而<dubbo:consumer>的retries屬性預設值為2。

消費者例項設定如下:

<dubbo:reference interface="com.web.gmall.service.UserService" 
		id="userService" timeout="5000" retries="3" >
		<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:reference>
//設定retries="3"表示除第一次呼叫外再嘗試呼叫三次,總共呼叫四次。

如果服務提供者如UserService有多個例項,消費者重試的時候還會嘗試呼叫其他UserService例項。

那麼是否所有情況下都應該設定重試次數?答案當然是否定的!

如果每次的操作結果都一樣,那麼應該可以進行重試,這種情況稱之為冪等。如果每次操作結果都不一樣,那麼不應該能夠重試,這種情況稱之為非冪等。冪等操作如查詢、刪除和修改,非冪等操作如新增。

舉個例子,如消費者呼叫提供者進行資料庫新增,在提供者插入資料庫過程中,消費者超時了,這時就不應該再次重試。

禁止重試,只需要將retries設定為0即可。如下所示:

<dubbo:reference interface="com.web.gmall.service.UserService" 
		id="userService" timeout="5000" retries="3" version="*">
		<dubbo:method name="insertUser" timeout="1000" retries="0"></dubbo:method>

介面級別可以重試三次,insertUser該方法禁止重試。

故而在系統設計的時候重試次數一定要額外注意,該值預設值為2。


【3】多版本

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

可以按照以下的步驟進行版本遷移:

0.在低壓力時間段,先升級一半提供者為新版本
1.再將所有消費者升級為新版本
2.然後將剩下的一半提供者升級為新版本

老版本服務提供者配置:

<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服務提供者配置:

<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服務消費者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服務消費者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果不需要區分版本,可以按照以下的方式配置 :

<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

這樣就可以從舊版本平滑過渡到新版本,也就是Dubbo官網介紹的灰度釋出。


【4】本地存根Stub

遠端服務後,客戶端通常只剩下介面,而實現全在伺服器端,但提供方有些時候想在客戶端也執行部分邏輯,比如:做 ThreadLocal 快取,提前驗證引數,呼叫失敗後偽造容錯資料等等,此時就需要在 API 中帶上 Stub,客戶端生成 Proxy 例項,會把 Proxy 通過建構函式傳給 Stub,然後把 Stub 暴露給使用者,Stub 可以決定要不要去調 Proxy。

在這裡插入圖片描述

dubbo:service的stub屬性

值型別為class/boolean,預設值為false。設為true,表示使用預設代理類名,即:介面名 + Local字尾,服務介面客戶端本地代理類名,用於在客戶端執行本地邏輯,如本地快取等,該本地代理類的建構函式必須允許傳入遠端代理物件,建構函式如:public XxxServiceLocal(XxxService xxxService)

例項

如下所示,這裡將介面抽取到了gmall-interface專案中,order-service-consumer和user-service-provider均依賴該專案。故而在gmall-interface專案中,新增UserServiceStub即可。

UserServiceStub例項如下:

public class UserServiceStub implements UserService {
	
	private final UserService userService;
	

	/**
	 * 傳入的是userService遠端的代理物件
	 * @param userService
	 */
	public UserServiceStub(UserService userService) {
		super();
		this.userService = userService;
	}


	@Override
	public List<UserAddress> getUserAddressList(String userId) {
		// TODO Auto-generated method stub
		System.out.println("UserServiceStub.....");
		if(userId!=null&&userId!="") {
			return userService.getUserAddressList(userId);
		}
		return null;
	}

}

在user-service-provider專案中配置如下:

<dubbo:service  interface="com.web.gmall.service.UserService" 
		ref="userServiceImpl" timeout="1000"  
		stub="com.web.gmall.service.stub.UserServiceStub" >
		<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
</dubbo:service>

分別啟動provider和consumer,測試如下:

使用者id:1
UserServiceStub.....
北京市昌平區巨集福科技園綜合樓3層
深圳市寶安區西部矽谷大廈B座3層(深圳分校)
呼叫完成...

可以看到在發起遠端呼叫之前,首先呼叫了UserServiceStub 。