Dubbo官網實戰使用技巧
原文鏈接:Dubbo官網實戰使用技巧
1、啟動時檢查:
我們檢查依賴的服務是否啟動,可利用下面三個屬性,優先順序從左到右逐漸降低。
如果服務不是強依賴,或者說服務之間可能存在死循環依賴,我們應該將 check 置為 false。
檢查判斷優先順序:
dubbo.reference.check
> dubbo.consumer.check
> dubbo.registry.check
2、只訂閱:
一般在開發環境時,我們新開發的介面都還不能發布出去,所以我們本地的服務不能往註冊中心註冊;
而且,如果我們將本地服務註冊上去,會影響別的服務的聯調,所以我們會利用下面屬性,將服務設置為只訂閱,不往註冊中心註冊。
dubbo.registry.register=false
dubbo.registry.subscribe=true
3、集群容錯:
集群容錯模式可利用 dubbo.reference.cluster
、dubbo.consumer.cluster
和 dubbo.service.cluster
、dubbo.provider.cluster
等屬性配置。
集群容錯中主要有幾個角色:
Invoker:Provider 的一個可調用 Service 的抽象,Invoker 封裝了 Provider 地址以及 Service 介面資訊。
Directory:代表多個 Invoker ,可以把它看成是 List
Cluster:將 Directory 中的多個 Invoker 偽裝成一個 Invoker,對上層透明,偽裝過程包含了容錯邏輯,調用失敗後,重試另一個。
Router:負責從多個 Invoker 中按路由規則選出子集,比如讀寫分離,應用隔離等。
LoadBalance:負責從多個 Invoker 中選出具體的一個用於本次調用,選的過程包含了負載均衡演算法,調用失敗後,需要重選
dubbo 提供的集群容錯模式:
Failover Cluster:失敗自動切換,當出現失敗,重試其它伺服器。通常用於讀操作,但重試會帶來更長延遲。可通過 retries=”2″ 來設置重試次數(不含第一次)。
Failfast Cluster:快速失敗,即只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作。
Failsafe Cluster:失敗安全,出現異常時直接忽略掉。通常用於寫入審計日誌等不重要的操作。
Failback Cluster:失敗自動恢復,後台記錄失敗請求,定時重發。通常用於消息通知操作。
Forking Cluster:並行調用多個伺服器,只要一個成功就返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=”2″ 來設置最大並行數。
Broadcast Cluster:廣播調用所有提供者,逐個調用,任意一台報錯則報錯。通常用於通知所有提供者更新快取或日誌等本地資源資訊。
4、負載均衡:
在集群負載均衡時,Dubbo 提供了多種均衡策略,預設為 random 隨機調用。
Random LoadBalance:
- 隨機,按權重設置隨機概率。
- 在一個截面上碰撞的概率高,但調用量越大分布越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。
RoundRobin LoadBalance:
- 輪詢,按公約後的權重設置輪詢比率。
- 存在慢的提供者累積請求的問題,比如:第二台機器很慢,但沒掛,當請求調到第二台時就卡在那,久而久之,所有請求都卡在調到第二台上。
LeastActive LoadBalance:
- 最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。
- 使慢的提供者收到更少請求,因為越慢的提供者的調用前後計數差會越大。
ConsistentHash LoadBalance:
- 一致性 Hash,相同參數的請求總是發到同一提供者。
- 當某一台提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
- 演算法參見://en.wikipedia.org/wiki/Consistent_hashing
- 預設只對第一個參數 Hash,如果要修改,請配置 <dubbo:parameter key=”hash.arguments” value=”0,1″ />
預設用 160 份虛擬節點,如果要修改,請配置 <dubbo:parameter key=”hash.nodes” value=”320″ />
可在服務端服務級別、客戶端服務級別、服務端方法級別和客戶端方法級別設置。
服務端服務級別&客戶端服務級別配置:
dubbo.provider.loadbalance=leastactive
dubbo.consumer.loadbalance=leastactive
服務端方法級別和客戶端方法級別配置:
@DubboService(interfaceClass = DubboServiceOne.class,loadbalance = "random",
methods = {
@Method(name="sayHello",loadbalance = "leastActive")
})
public class DubboServiceOneImpl implements DubboServiceOne {}
@DubboReference(loadbalance = "random",
methods = {
@Method(name="sayHello",loadbalance = "leastactive")
})
private DubboServiceOne DubboServiceOne;
5、直連提供者
在開發及測試環境下,經常需要繞過註冊中心,只測試指定服務提供者,這時候可能需要點對點直連,點對點直連方式,將以服務介面為單位,忽略註冊中心的提供者列表,A 介面配置點對點,不影響 B 介面從註冊中心獲取列表。
在 JVM 啟動參數中加入 -D 參數映射服務地址:
java -D com.alibaba.xxx.XxxService=dubbo://localhost:20890
在<dubbo.reference>
標籤或者@DubboResource註解
中增加 url 屬性。
<debbo.reference url="dubbo://localhost:20890" interfaceClass=""/>
@DubboReference(url="dubbo://localhost:20890")
private DubboServiceOne DubboServiceOne;
6、本地調用
本地調用使用了 injvm 協議,是一個偽協議,它不開啟埠,不發起遠程調用,只在 JVM 內直接關聯,但執行 Dubbo 的 Filter 鏈。
protocol、provider、consumer、service、reference 都可以設置。
7、本地存根
遠程服務後,客戶端通常只剩下介面,而實現全在伺服器端,但提供方有些時候想在客戶端也執行部分邏輯,比如:做 ThreadLocal 快取,提前驗證參數,調用失敗後偽造容錯數據等等,此時就需要在 API 中帶上 Stub,客戶端生成 Proxy 實例,會把 Proxy 通過構造函數傳給 Stub ,然後把 Stub 暴露給用戶,Stub 可以決定要不要去調 Proxy。
Sub 利用 dubbo.service.sub
屬性設置。
例子:
假設服務提供者提供了一個介面,DubboServiceOne,然後服務消費者要做本地存根,只需要在自己的項目中,增加一個 DubboServiceOne 介面的實現類,然後在 @DubboReference
註解或者 <dubbo:reference>
標籤增加 stub 屬性即可。
實現類:
/**
* DubboServiceOne 本地存根
* @author winfun
* @date 2021/2/1 9:59 上午
**/
@Slf4j
public class DubboServiceOneStub implements DubboServiceOne {
private final DubboServiceOne dubboServiceOne;
public DubboServiceOneStub(DubboServiceOne dubboServiceOne){
this.dubboServiceOne = dubboServiceOne;
}
/***
* say hello
* @author winfun
* @param name name
* @return {@link ApiResult <String> }
**/
@Override
public ApiResult<String> sayHello(String name) {
try {
ApiResult<String> result = this.dubboServiceOne.sayHello(name);
if (ApiContants.SUCCESS.equals(result.getCode())){
return ApiResult.fail(ApiContants.FAIL,"業務異常",result.getData());
}
}catch (Exception e){
log.error("call DubboServiceOne throw exception!message is {}",e.getMessage());
return ApiResult.fail("調用失敗");
}
return null;
}
}
使用:
/**
* 測試本地存根
* @author winfun
* @date 2021/2/1 10:26 上午
**/
@RestController
public class TestStubController {
@DubboReference(lazy = true,check = false,stub = "com.winfun.demo.stub.DubboServiceOneStub")
private DubboServiceOne dubboServiceOne;
@GetMapping("/stub/{name}")
public ApiResult<String> testStub(@PathVariable("name") String name){
return this.dubboServiceOne.sayHello(name);
}
}
8、本地偽裝
本地偽裝通常用於服務降級,比如某驗權服務,當服務提供方全部掛掉後,客戶端不拋出異常,而是通過 mock 數據返回授權失敗。
mock 是 sub 的一個子集,mock是發生了錯誤,也就是拋出 RpcException 異常時會觸發;而使用 sub,那麼就需要在程式捕獲異常,然後進行處理。
mock 機制可利用<dubbo.reference>
標籤或者@DubboReference
的mock屬性設置。
詳細可看我自己寫的文章://blog.csdn.net/Howinfun/article/details/113439208
9、服務延遲暴露
Dubbo 2.6.5 之後,所有服務都將在 Spring 初始化完成後進行暴露,如果你不需要延遲暴露服務,無需配置 delay。
可使用 dubbo.service.delay
屬性來設置延遲多少秒暴露服務。delay 的時間單位為毫秒。
10、並發控制
並發控制都是在服務提供者端設置的。
首先,可通過 dubbo.service.executes
屬性限制服務端每個方法的並發量(佔用執行緒池執行緒數)、通過 dubbo.method.executes
(服務端) 屬性直接將並發限制具體到介面的某個方法。
還可以通過 dubbo.service.actives
/dubbo.reference.actives
屬性控制介面每個方法每個客戶端的並發執行數;
通過 dubbo.method.actives
(兩端) 屬性直接將並發執行控制到介面的某個方法。