Dubbo API 筆記——Dubbo架構與使用

架構演變

  • 單一應用架構

    所有功能部署在一個應用上,用於簡化增刪改查工作量的數據訪問框架(ORM)是關鍵

  • 垂直應用架構

    將應用拆分成互不相干的幾個應用,以提升效率,此時,用於加速前端頁面開發的Web框架(MVC)是關鍵

  • 分佈式服務架構

    將核心業務抽取出來,作爲獨立的服務,逐漸形成穩定的服務中心,此時,用於提高業務複用及整合的分佈式服務框架(RPC)是關鍵

  • 流動計算架構

    增加一個調度中心基於訪問壓力實時管理集羣容量,提高集羣利用率,此時,用於提高機器利用率的資源調度和治理中心(SOA)是關鍵

Dubbo架構

<img du_002>

節點角色說明

節點 角色說明
Provider 暴露服務的服務提供方
Consumer 調用遠程服務的服務消費方
Registry 服務註冊與發現的註冊中心
Monitor 統計服務的調用次數和調用時間的監控中心
Container 服務運行容器

調用關係說明

  • 服務容器負責啓動,加載,運行服務提供者
  • 服務提供者在啓動時,向註冊中心註冊自己提供的服務
  • 服務消費者在啓動時,向註冊中心訂閱自己所需的服務
  • 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連接推送變更數據給消費者
  • 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,如果調用失敗,再選另一臺調用
  • 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心

Dubbo架構特性

  • 連通性

    • 服務提供者和消費者只在啓動時與註冊中心交互,註冊中心不轉發請求,壓力較小
    • 監控中心負責統計各服務調用次數,調用時間等,統計先在內存彙總後每分鐘一次發送到監控中心服務器,並以報表展示
    • 服務提供者向註冊中心註冊其提供的服務,並彙報調用時間到監控中心,此時間不包含 網絡開銷
    • 服務消費者向註冊中心獲取服務提供者地址列表,並根據負載算法直接調用提供者,同時彙報調用時間到監控中心,此時間包含網絡開銷
    • 註冊中心,服務提供者,服務消費者三者之間均爲長連接,監控中心除外
    • 註冊中心通過長連接感知服務提供者的存在,服務提供者宕機,註冊中心將立即推送事件通知消費者
    • 註冊中心和監控中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表
    • 註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者
  • 健壯性

    • 監控中心宕掉不影響使用,只是丟失部分採樣數據
    • 數據庫宕掉後,註冊中心仍能通過緩存提供服務列表查詢,但不能註冊新服務
    • 註冊中心對等集羣,任意一臺宕掉後,將自動切換到另一臺
    • 註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地緩存通訊
    • 服務提供者無狀態,任意一臺宕掉後,不影響使用
    • 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復
  • 伸縮性

    • 註冊中心爲對等集羣,可動態增加機器部署實例,所有客戶端將自動發現新的註冊中心
    • 服務提供者無狀態,可動態增加機器部署實例,註冊中心將推送新的服務提供者信息給消費者
  • 升級性

    • 當服務集羣規模進一步擴大,帶動IT治理結構進一步升級,需要實現動態部署,進行流動計算,現有分佈式服務架構不會帶來阻力。下圖是未來可能的一種架構:

    <img du_003>

    • 節點角色說明
    節點 角色說明
    Deployer 自動部署服務的本地代理
    Repository 倉庫用於存儲服務應用發佈包
    Scheduler 調度中心基於訪問壓力自動增減服務提供者
    Admin 統一管理控制檯
    Registry 服務註冊與發現的註冊中心
    Monitor 統計服務的調用次數和調用時間的監控中心

配置標籤

標籤 用途 解釋
<dubbo:service /> 服務配置 用於暴露一個服務,定義服務的元信息,一個服務可以用多個協議暴露,一個服務也可以註冊到多個註冊中心
引用配置 用於創建一個遠程服務代理,一個引用可以指向多個註冊中心
<dubbo:protocol /> 協議配置 用於配置提供服務的協議信息,協議由提供方指定,消費方被動接受
<dubbo:application /> 應用配置 用於配置當前應用信息,不管該應用是提供者還是消費者
<dubbo:module /> 模塊配置 用於配置當前模塊信息,可選
<dubbo:registry /> 註冊中心配置 用於配置連接註冊中心相關信息
<dubbo:monitor /> 監控中心配置 用於配置連接監控中心相關信息,可選
<dubbo:provider /> 提供方配置 當ProtocolConfig和ServiceConfig某屬性沒有配置時,採用此缺省值,可選
<dubbo:consumer /> 消費方配置 當ReferenceConfig某屬性沒有配置時,採用此缺省值,可選
<dubbo:method /> 方法配置 用於ServiceConfig和ReferenceConfig指定方法級的配置信息
<dubbo:argument /> 參數配置 用於指定方法參數配置

配置覆蓋關係

  • 方法級 > 接口級 > 全局配置
  • 級別相同,則消費方優先
  • 服務提供方配置,通過URL經由註冊中心傳遞給消費方
  • dubbo.properties通常用於共享公共配置,比如應用名,優先級低於XML配置

註解配置

服務提供方

import com.alibaba.dubbo.config.annotation.Service;
@Service(version="1.0.0") 
public class FooServiceImpl implements FooService {

    //  ... 

}

// XML配置
<!--    公共信息,也可以用dubbo.properties配置 --> 
<dubbo:application name="annotation-provider" /> 
<dubbo:registry address="127.0.0.1:4548" />

<!--    掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中所有的類 --> 
<dubbo:annotation package="com.foo.bar.service" />

服務消費方

import com.alibaba.dubbo.config.annotation.Reference; 
import org.springframework.stereotype.Component;

@Component 
public class BarAction  {                   
    @Reference(version="1.0.0")             
    private FooService fooService; 
}

// XML配置
<!--    公共信息,也可以用dubbo.properties配置 --> 
<dubbo:application name="annotation-consumer" /> 
<dubbo:registry address="127.0.0.1:4548" />

<!--    掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中所有的類 --> 
<dubbo:annotation package="com.foo.bar.action" />

也可以通過以下的XML配置完成annotation掃描,與前面的等價

<dubbo:annotation /> 
<context:component-scan base-package="com.foo.bar.service">             
    <context:include-filter type="annotation" expression="com.alibaba.dubbo.config.annotation.Service" /> 
</context:component-scan>

啓動時檢查

Dubbo 缺省會在啓動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止 Spring 初始化完成,以便上線時,能及早發現問題,默認 check=”true”,懶加載或通過API編程延遲引用服務時可check

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

    <dubbo:reference interface="com.foo.BarService" check="false" />
    
  • 關閉所有服務的啓動時檢查(沒有提供者時報錯)

    <dubbo:consumer check="false" />
    
  • 關閉註冊中心啓動時檢查(註冊訂閱失敗時報錯)

    <dubbo:registry check="false" />
    

集羣容錯

在集羣調用失敗時,Dubbo提供了多種容錯方案,缺省爲failover重試

<img du_004>

Failover Cluster

失敗自動切換,當出現失敗,重試其它服務器。通常用於讀操作,但重試會帶來更長延遲。 可通過retries=”2” 來設置重試次數(不含第一次)

<dubbo:service retries="2" />

或

<dubbo:reference retries="2" />

或

<dubbo:reference>               
    <dubbo:method name="findFoo" retries="2" /> 
</dubbo:reference>

Failfast Cluster

快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄

Failsafe Cluster

失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作

<dubbo:service cluster="failsafe" />

或

<dubbo:reference cluster="failsafe" />

Failback Cluster

失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作

Forking Cluster

並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks=”2” 來設置最大並行數

Broadcast Cluster

廣播調用所有提供者,逐個調用,任意一臺報錯則報錯。通常用於通知所有提供者更新緩存或日誌等本地資源信息。

負載均衡

在集羣負載均衡時,Dubbo 提供了多種均衡策略,缺省爲 random 隨機調用

配置

<!-- 服務端服務級別 -->
<dubbo:service interface="..." loadbalance="roundrobin" />

<!-- 客戶端服務級別 -->
<dubbo:reference interface="..." loadbalance="roundrobin" />

<!-- 服務端方法級別 -->
<dubbo:service interface="...">             
    <dubbo:method name="..." loadbalance="roundrobin" /> 
</dubbo:service>

<!-- 客戶端方法級別 -->
<dubbo:reference interface="...">               
    <dubbo:method name="..." loadbalance="roundrobin" /> 
</dubbo:reference>

Random LoadBalance

  • 隨機,按權重設置隨機概率
  • 在一個截面上碰撞的概率高,但調用量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重

RoundRobin LoadBalance

  • 輪詢,按公約後的權重設置輪詢比率
  • 存在慢的提供者累計請求的問題,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上

LeastActive LoadBalance

  • 最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差
  • 使慢的提供者收到更少請求,因爲越慢的提供者的調用前後計數差會越大

ConsistentHash LoadBalance

  • 一致性Hash,相同參數的請求總是發到同一提供者
  • 當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動
  • 缺省只對第一個參數Hash,如果要修改,配置

    <dubbo:parameter key="hash.arguments" value="0,1" />    
    
  • 缺省用 160 份虛擬節點,如果要修改,配置

    <dubbo:parameter key="hash.nodes" value="320" />
    

線程模型

如果事件處理的邏輯能迅速完成,並且不會發起新的 IO 請求,比如只是在內存中記個標識,則直接在 IO 線程上處理更快,因爲減少了線程池調度

但如果事件處理邏輯較慢,或者需要發起新的 IO 請求,比如需要查詢數據庫,則必須派發到線程池,否則 IO 線程阻塞,將導致不能接收其它請求

如果用 IO 線程處理事件,又在事件處理過程中發起新的 IO 請求,比如在連接事件中發起登錄請求,會報“可能引發死鎖”異常,但不會真死鎖

<img du_005>

因此,需要通過不同的派發策略和不同的線程池配置的組合來應對不同的場景

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />

Dispatcher

  • all

    所有消息都派發到線程池,包括請求,響應,連接事件,斷開事件,心跳等

  • direct

    所有消息都不派發到線程池,全部在 IO 線程上直接執行

  • message

    只有請求響應消息派發到線程池,其它連接斷開事件,心跳等消息,直接在IO 線程上執行

  • execution

    只請求消息派發到線程池,不含響應,響應和其它連接斷開事件,心跳等消息,直接在 IO 線程上執行

  • connection

    在 IO 線程上,將連接斷開事件放入隊列,有序逐個執行,其它消息派發到線程池

ThreadPool

  • fixed

    fixed 固定大小線程池,啓動時建立線程,不關閉,一直持有(缺省)

  • cached

    緩存線程池,空閒一分鐘自動刪除,需要時重建

  • limited

    可伸縮線程池,但池中的線程數只會增長不會收縮。只增長不收縮的目的是爲了避免收縮時突然來了大流量引起的性能問題

直連提供者

繞過註冊中心,只測試指定服務提供者(只應在測試階段使用)

<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" />

只訂閱

爲方便開發測試,經常會在線下共用一個所有服務可用的註冊中心,讓服務提供者開發方,只訂閱服務(開發的服務可能依賴其它服務),而不註冊正在開發的服務,通過直連測試正在開發的服務

<img du_007>

禁用註冊配置

<dubbo:registry address="10.20.153.10:9090" register="false" />

或

<dubbo:registry address="10.20.153.10:9090?register=false" />

只註冊

如果有兩個鏡像環境,兩個註冊中心,有一個服務只在其中一個註冊中心有部署,另一個註冊中心還沒來得及部署,而兩個註冊中心的其它應用都需要依賴此服務。這個時候,可以讓服務提供者方只註冊服務到另一註冊中心,而不從另一註冊中心訂閱服務

禁用訂閱配置

<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" />
<dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" />

或

<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" />
<dubbo:registry id="qdRegistry" address="10.20.141.150:9090?subscribe=false" />

靜態服務

有時候希望人工管理服務提供者的上線和下線,此時需將註冊中心標識爲非動態管理模式

<dubbo:registry address="10.20.141.150:9090" dynamic="false" />

或

<dubbo:registry address="10.20.141.150:9090?dynamic=false" />

服務提供者初次註冊時爲禁用狀態,需人工啓用。斷線時,將不會被自動刪除,需人工禁用

多協議

Dubbo 允許配置多協議,在不同服務上支持不同協議或者同一服務上同時支持多種協議

不同服務在性能上適用不同協議進行傳輸,比如大數據用短連接協議,小數據大併發用長連接協議

多註冊中心

Dubbo 支持同一服務向多註冊中心同時註冊,或者不同服務分別註冊到不同的註冊中心上去,甚至可以同時引用註冊在不同註冊中心上的同名服務。另外,註冊中心是支持自定義擴展的

多註冊中心註冊

<!--    多註冊中心配置 -->             
<dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" />    
<!--    向多個註冊中心註冊   -->             
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" />

多註冊中心引用

<!--    多註冊中心配置 -->             
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />              
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
<!--    引用中文站服務 -->             
<dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloServ ice" version="1.0.0" registry="chinaRegistry" />             <!--    引用國際站站服務    -->             
<dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloServi ce" version="1.0.0" registry="intlRegistry" /> 

<!--    多註冊中心配置,豎號分隔表示同時連接多個不同註冊中心,同一註冊中心的多個集羣地址用逗號分隔   -->             
<dubbo:registry address="10.20.141.150:9090|10.20.154.177:9010" />              
<!--    引用服務    -->             
<dubbo:reference id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" /> 

服務分組

當一個接口有多種實現時,可以用 group 區分

服務

<dubbo:service group="feedback" interface="com.xxx.IndexService" /> 
<dubbo:service group="member" interface="com.xxx.IndexService" />

引用

<dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" /> 
<dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndewxService" />

<!-- 任意組(總是隻調一個可用組的實現) -->
<dubbo:reference id="barService" interface="com.foo.BarService" group="*" />

多版本

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

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

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

    <dubbo:service  interface="com.foo.BarService"  version="2.0.0" />
    
    <dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
    
    <!-- 不區分版本 -->
    <dubbo:reference id="barService" interface="com.foo.BarService" version="*" />
    

分組聚合

消費方需從每種group中調用一次返回結果,合併結果返回,實現聚合菜單項

配置

搜索所有分組

<dubbo:reference interface="com.xxx.MenuService"    group="*" merger="true" />

合併指定分組

<dubbo:reference interface="com.xxx.MenuService" group="aaa,bbb" merger="true" />

指定方法合併結果,其它未指定的方法,將只調用一個Group

<dubbo:reference interface="com.xxx.MenuService" group="*">             
    <dubbo:method name="getMenuItems" merger="true" /> 
</dubbo:service>

某個方法不合並結果,其它都合併結果

<dubbo:reference interface="com.xxx.MenuService" group="*" merger="true">               
    <dubbo:method name="getMenuItems" merger="false" /> 
</dubbo:service>

指定合併策略,缺省根據返回值類型自動匹配,如果同一類型有兩個合併器時,需指定合併器的名稱

<dubbo:reference interface="com.xxx.MenuService" group="*">             
    <dubbo:method name="getMenuItems" merger="mymerge" /> 
</dubbo:service>

指定合併方法,將調用返回結果的指定方法進行合併,合併方法的參數類型必須是返回結果類型本身

<dubbo:reference interface="com.xxx.MenuService" group="*">             
    <dubbo:method name="getMenuItems" merger=".addAll" />
</dubbo:service>

回聲測試

回聲測試用於檢測服務是否可用,回聲測試按照正常請求流程執行,能夠測試整個調用是否通暢,可用於監控

所有服務自動實現 EchoService 接口,只需將任意服務引用強制轉型爲 EchoService ,即可使用

<dubbo:reference id="memberService" interface="com.xxx.MemberService" />

代碼

// 遠程服務引用 MemberService 
memberService = ctx.getBean("memberService");   
EchoService echoService = (EchoService) memberService; // 強制轉型爲EchoService
// 回聲測試可用性 
String status = echoService.$echo("OK");   
assert(status.equals("OK"));

上下文信息

上下文中存放的是當前調用過程中所需的環境信息,所有配置信息都將轉換爲URL的參數

服務消費方

// 遠程調用 
xxxService.xxx(); 
// 本端是否爲消費端,這裏會返回true 
boolean isConsumerSide = RpcContext.getContext().isConsumerSide();
// 獲取最後一次調用的提供方IP地址 
String serverIP = RpcContext.getContext().getRemoteHost(); 
// 獲取當前服務配置信息,所有配置信息都將轉換爲URL的參數 
String application = RpcContext.getContext().getUrl().getParameter("application"); 
// 注意:每發起RPC調用,上下文狀態會變化
yyyService.yyy();

服務提供方

public class XxxServiceImpl implements XxxService {
    public void xxx() {                             
        // 本端是否爲提供端,這裏會返回true                               
        boolean isProviderSide = RpcContext.getContext().isProviderSide();                              
        // 獲取調用方IP地址                    
        String clientIP = RpcContext.getContext().getRemoteHost();
        // 獲取當前服務配置信息,所有配置信息都將轉換爲URL的參數                 
        String application = RpcContext.getContext().getUrl().getParameter("applicatio n");             
        // 注意:每發起RPC調用,上下文狀態會變化                             
        yyyService.yyy();                   
        // 此時本端變成消費端,這裏會返回false 
        boolean isProviderSide = RpcContext.getContext().isProviderSide();  
    }   

}

異步調用

基於 NIO 的非阻塞實現並行調用,客戶端不需要啓動多線程即可完成並行調用多個遠程服務,相對多線程開銷較小

<img du_008>

在 consumer.xml 中配置

<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">                        
    <dubbo:method name="findFoo" async="true" /> 
</dubbo:reference> 

<dubbo:reference id="barService" interface="com.alibaba.bar.BarService">                        
    <dubbo:method name="findBar" async="true" /> 
</dubbo:reference>

調用代碼

// 此調用會立即返回null 
fooService.findFoo(fooId); 
// 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future
Future<Foo> fooFuture = RpcContext.getContext().getFuture();    

// 此調用會立即返回null 
barService.findBar(barId); 
// 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future 
Future<Bar> barFuture = RpcContext.getContext().getFuture();    

// 此時findFoo和findBar的請求同時在執行,客戶端不需要啓動多線程來支持並行,而是藉助NIO的非阻塞完成

// 如果foo已返回,直接拿到返回值,否則線程wait住,等待foo返回後,線程會被notify喚醒 
Foo foo = fooFuture.get();  
// 同理等待bar返回 
Bar bar = barFuture.get();  

// 如果foo需要5秒返回,bar需要6秒返回,實際只需等6秒,即可獲取到foo和bar,進行接下來的處理

可以設置是否等待消息發出

  • sent=”true” 等待消息發出,消息發送失敗將拋出異常
  • sent=”false” 不等待消息發出,將消息放入 IO 隊列,即刻返回

    <dubbo:method name="findFoo" async="true" sent="true" />
    

如果只是異步調用,完全忽略返回值,可以配置 return=”false”,以減少 Future 對象的創建和管理成本

<dubbo:method name="findFoo" async="true" return="false" />

本地存根

遠程服務後,客戶端通常只剩下接口,而實現全在服務器端,但提供方有些時候想在客戶端也執行部分邏輯,比如:做 ThreadLocal 緩存,提前驗證參數,調用失敗後僞造容錯數據等等,此時就需要在 API 中帶上 Stub,客戶端生成 Proxy 實例,會把 Proxy 通過構造函數傳給 Stub,然後把 Stub 暴露給用戶,Stub 可以決定要不要去調 Proxy

<img du_010>

配置

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

或

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

提供Stub的實現

package com.foo; 
public class BarServiceStub implements BarService { 
    private final BarService barService;

    // 構造函數傳入真正的遠程代理對象              
    public (BarService barService)  {                               
        this.barService = barService;               
    }

    public String sayHello(String name) {                               
        // 此代碼在客戶端執行,你可以在客戶端做ThreadLocal本地緩存,或預先驗證參數是否合法,等等                             
        try {                                   
            return barService.sayHello(name);   
        } catch (Exception e) {                                 
            // 你可以容錯,可以做任何AOP攔截事項                               
            return "容錯數據";                              
        }               
    } 
}

本地僞裝

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

配置

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

或

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

在工程中提供Mock實現

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

如果服務的消費方經常需要 try-catch 捕獲異常,可以考慮改爲 Mock(只有出現 RpcException 時才執行)實現,並在Mock實現中 return null,如果只是想簡單的忽略異常,在 2.0.11 以上版本可用

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

延遲暴露

如果服務需要預熱時間,比如初始化緩存,等待相關資源就位等,可以使用 delay 進行延遲暴露

延遲5秒暴露服務

<dubbo:service delay="5000" />

延遲到 Spring 初始化完成後,再暴露服務

<dubbo:service delay="-1" />

併發控制

  • 限制 com.foo.BarService 的每個方法,服務器端併發執行(或佔用線程池線程數)不能超過 10 個

    <dubbo:service interface="com.foo.BarService" executes="10" />
    
  • 限制 com.foo.BarService 的 sayHello 方法,服務器端併發執行(或佔用線程池線程數)不 能超過 10 個

    <dubbo:service interface="com.foo.BarService">              
        <dubbo:method name="sayHello" executes="10" /> 
    </dubbo:service>
    
  • 限制 com.foo.BarService 的每個方法,每客戶端併發執行(或佔用連接的請求數)不能超過 10 個

    <dubbo:service interface="com.foo.BarService" actives="10" />
    
    或
    
    <dubbo:reference interface="com.foo.BarService" actives="10" />
    
  • 限制 com.foo.BarService 的 sayHello 方法,每客戶端併發執行(或佔用連接的請求數)不 能超過 10 個

    <dubbo:service interface="com.foo.BarService">              
        <dubbo:method name="sayHello" actives="10" /> 
    </dubbo:service>
    
    或
    
    <dubbo:reference interface="com.foo.BarService">                
        <dubbo:method name="sayHello" actives="10" /> 
    </dubbo:service>
    

連接控制

服務端連接控制

限制服務器端接受的連接不能超過 10 個

<dubbo:provider protocol="dubbo" accepts="10" />

或

<dubbo:protocol name="dubbo" accepts="10" />

客戶端連接控制

限制客戶端服務使用連接不能超過 10 個

<dubbo:reference interface="com.foo.BarService" connections="10" />

或

<dubbo:service interface="com.foo.BarService" connections="10" />

延遲連接

延遲連接用於減少長連接數。當有調用發起時,再創建長連接

<dubbo:protocol name="dubbo" lazy="true" />

優雅停機

kill PID 可以實現,kill -9 PID 不可以

原理

服務提供方

  • 停止時,先標記爲不接收新請求,新請求過來時直接報錯,讓客戶端重試其它機器
  • 然後,檢測線程池中的線程是否正在運行,如果有,等待所有線程執行完成,除非超時,則強制關閉

服務消費方

  • 停止時,不再發起新的調用請求,所有新的調用在客戶端即報錯
  • 然後,檢測有沒有請求的響應還沒有返回,等待響應返回,除非超時,則強制關閉

設置停機超時時間,缺省超時時間是10秒

<dubbo:application ...>             
    <dubbo:parameter key="shutdown.timeout" value="60000" /> <!-- 單位毫秒 --> 
</dubbo:application>
發佈了84 篇原創文章 · 獲贊 135 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章