dubbo用戶指南

用戶指南

入門

(+) (#)javascript

背景

(#)html

隨着互聯網的發展,網站應用的規模不斷擴大,常規的垂直應用架構已沒法應對,分佈式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。前端

  • 單一應用架構
    • 當網站流量很小時,只需一個應用,將全部功能都部署在一塊兒,以減小部署節點和成本。
    • 此時,用於簡化增刪改查工做量的 數據訪問框架(ORM) 是關鍵。
  • 垂直應用架構
    • 當訪問量逐漸增大,單一應用增長機器帶來的加速度愈來愈小,將應用拆成互不相干的幾個應用,以提高效率。
    • 此時,用於加速前端頁面開發的 Web框架(MVC) 是關鍵。
  • 分佈式服務架構
    • 當垂直應用愈來愈多,應用之間交互不可避免,將核心業務抽取出來,做爲獨立的服務,逐漸造成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。
    • 此時,用於提升業務複用及整合的 分佈式服務框架(RPC) 是關鍵。
  • 流動計算架構
    • 當服務愈來愈多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增長一個調度中心基於訪問壓力實時管理集羣容量,提升集羣利用率。
    • 此時,用於提升機器利用率的 資源調度和治理中心(SOA) 是關鍵。

需求

(#)java

在大規模服務化以前,應用可能只是經過RMI或Hessian等工具,簡單的暴露和引用遠程服務,經過配置服務的URL地址進行調用,經過F5等硬件進行負載均衡。node

(1) 當服務愈來愈多時,服務URL配置管理變得很是困難,F5硬件負載均衡器的單點壓力也愈來愈大。linux

此時須要一個服務註冊中心,動態的註冊和發現服務,使服務的位置透明。git

並經過在消費方獲取服務提供方地址列表,實現軟負載均衡和Failover,下降對F5硬件負載均衡器的依賴,也能減小部分紅本。github

(2) 當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪一個應用要在哪一個應用以前啓動,架構師都不能完整的描述應用的架構關係。web

這時,須要自動畫出應用間的依賴關係圖,以幫助架構師理清理關係。redis

(3) 接着,服務的調用量愈來愈大,服務的容量問題就暴露出來,這個服務須要多少機器支撐?何時該加機器?

爲了解決這些問題,第一步,要將服務如今天天的調用量,響應時間,都統計出來,做爲容量規劃的參考指標。

其次,要能夠動態調整權重,在線上,將某臺機器的權重一直加大,並在加大的過程當中記錄響應時間的變化,直到響應時間到達閥值,記錄此時的訪問量,再以此訪問量乘以機器數反推總容量。

以上是Dubbo最基本的幾個需求,更多服務治理問題參見:

http://code.alibabatech.com/blog/experience_1402/service-governance-process.html

架構

(#)

節點角色說明:

  • Provider: 暴露服務的服務提供方。
  • Consumer: 調用遠程服務的服務消費方。
  • Registry: 服務註冊與發現的註冊中心。
  • Monitor: 統計服務的調用次調和調用時間的監控中心。
  • Container: 服務運行容器。

調用關係說明:

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

(1) 連通性:

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

(2) 健狀性:

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

(3) 伸縮性:

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

(4) 升級性:

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

  • Deployer: 自動部署服務的本地代理。
  • Repository: 倉庫用於存儲服務應用發佈包。
  • Scheduler: 調度中心基於訪問壓力自動增減服務提供者。
  • Admin: 統一管理控制檯。

用法

(#)

本地服務:(Spring配置)

local.xml
< bean id=「xxxService」 class=「com.xxx.XxxServiceImpl」 />
 
< bean id=「xxxAction」 class=「com.xxx.XxxAction」>
     < property name=「xxxService」 ref=「xxxService」 />
</ bean >

遠程服務:(Spring配置)

在本地服務的基礎上,只需作簡單配置,便可完成遠程化:

  • 將上面的local.xml配置拆分紅兩份,將服務定義部分放在服務提供方remote-provider.xml,將服務引用部分放在服務消費方remote-consumer.xml。
  • 並在提供方增長暴露服務配置<dubbo:service>,在消費方增長引用服務配置<dubbo:reference>。

以下:

remote-provider.xml
< bean id=「xxxService」 class=「com.xxx.XxxServiceImpl」 /> <!-- 和本地服務同樣實現遠程服務 -->
 
< dubbo:service interface=「com.xxx.XxxService」 ref=「xxxService」 /> <!-- 增長暴露遠程服務配置 -->
remote-consumer.xml
< dubbo:reference id=「xxxService」 interface=「com.xxx.XxxService」 /> <!-- 增長引用遠程服務配置 -->
 
< bean id=「xxxAction」 class=「com.xxx.XxxAction」> <!-- 和本地服務同樣使用遠程服務 -->
     < property name=「xxxService」 ref=「xxxService」 />
</ bean >

快速啓動

(+) (#)

Dubbo採用全Spring配置方式,透明化接入應用,對應用沒有任何API侵入,只需用Spring加載Dubbo的配置便可,Dubbo基於Spring的Schema擴展進行加載。
若是不想使用Spring配置,而但願經過API的方式進行調用(不推薦),請參見:API配置 (+)

服務提供者

(#)

完整安裝步驟,請參見:示例提供者安裝 (+)

定義服務接口: (該接口需單獨打包,在服務提供方和消費方共享)

DemoService.java
package com.alibaba.dubbo.demo;
 
public interface DemoService {
 
     String sayHello(String name);
 
}

在服務提供方實現接口:(對服務消費方隱藏實現)

DemoServiceImpl.java
package com.alibaba.dubbo.demo.provider;
 
import com.alibaba.dubbo.demo.DemoService;
 
public class DemoServiceImpl implements DemoService {
 
     public String sayHello(String name) {
         return "Hello " + name;
     }
 
}

用Spring配置聲明暴露服務:

provider.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
     xsi:schemaLocation = "http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
 
     <!-- 提供方應用信息,用於計算依賴關係 -->
     < dubbo:application name = "hello-world-app"  />
 
     <!-- 使用multicast廣播註冊中心暴露服務地址 -->
     < dubbo:registry address = "multicast://224.5.6.7:1234" />
 
     <!-- 用dubbo協議在20880端口暴露服務 -->
     < dubbo:protocol name = "dubbo" port = "20880" />
 
     <!-- 聲明須要暴露的服務接口 -->
     < dubbo:service interface = "com.alibaba.dubbo.demo.DemoService" ref = "demoService" />
 
     <!-- 和本地bean同樣實現服務 -->
     < bean id = "demoService" class = "com.alibaba.dubbo.demo.provider.DemoServiceImpl" />
 
</ beans >

加載Spring配置:

Provider.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Provider {
 
     public static void main(String[] args) throws Exception {
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "http://10.20.160.198/wiki/display/dubbo/provider.xml" });
         context.start();
 
         System.in.read(); // 按任意鍵退出
     }
 
}

服務消費者

(#)

完整安裝步驟,請參見:示例消費者安裝 (+)

經過Spring配置引用遠程服務:

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
     xsi:schemaLocation = "http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
 
     <!-- 消費方應用名,用於計算依賴關係,不是匹配條件,不要與提供方同樣 -->
     < dubbo:application name = "consumer-of-helloworld-app"  />
 
     <!-- 使用multicast廣播註冊中心暴露發現服務地址 -->
     < dubbo:registry address = "multicast://224.5.6.7:1234" />
 
     <!-- 生成遠程服務代理,能夠和本地bean同樣使用demoService -->
     < dubbo:reference id = "demoService" interface = "com.alibaba.dubbo.demo.DemoService" />
 
</ beans >

加載Spring配置,並調用遠程服務:(也能夠使用IoC注入)

Consumer.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.alibaba.dubbo.demo.DemoService;
 
public class Consumer {
 
     public static void main(String[] args) throws Exception {
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "http://10.20.160.198/wiki/display/dubbo/consumer.xml" });
         context.start();
 
         DemoService demoService = (DemoService)context.getBean( "demoService" ); // 獲取遠程服務代理
         String hello = demoService.sayHello( "world" ); // 執行遠程方法
 
         System.out.println( hello ); // 顯示調用結果
     }
 
}

依賴

(+) (#)

必需依賴

  • JDK1.5+
理論上Dubbo能夠只依賴JDK,不依賴於任何三方庫運行,只需配置使用JDK相關實現策略。

缺省依賴

經過mvn dependency:tree > dep.log命令分析,Dubbo缺省依賴如下三方庫:

[INFO] +- com.alibaba:dubbo:jar:2.1.2:compile
[INFO] |  +- log4j:log4j:jar:1.2.16:compile
[INFO] |  +- org.javassist:javassist:jar:3.15.0-GA:compile
[INFO] |  +- org.springframework:spring:jar:2.5.6.SEC03:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  \- org.jboss.netty:netty:jar:3.2.5.Final:compile

這裏全部依賴都是換照Dubbo缺省配置選的,這些缺省值是基於穩定性和性能考慮的。

  • log4j.jar和commons-logging.jar日誌輸出包。
    • 能夠直接去掉,dubbo自己的日誌會自動切換爲JDK的java.util.logging輸出。
    • 但若是其它三方庫好比spring.jar間接依賴commons-logging,則不能去掉。
  • javassist.jar 字節碼生成。
    • 若是<dubbo:provider proxy="jdk" />或<dubbo:consumer proxy="jdk" />,以及<dubbo:application compiler="jdk" />,則不須要。
  • spring.jar 配置解析。
    • 若是用ServiceConfig和ReferenceConfig的API調用,則不須要。
  • netty.jar 網絡傳輸。
    • 若是<dubbo:protocol server="mina"/>或<dubbo:protocol server="grizzly"/>,則換成mina.jar或grizzly.jar。
    • 若是<protocol name="rmi"/>,則不須要。

可選依賴

如下依賴,在主動配置使用相應實現策略時用到,需自行加入依賴。

  • mina: 1.1.7
  • grizzly: 2.1.4
  • httpclient: 4.1.2
  • hessian_lite: 3.2.1-fixed
  • xstream: 1.4.1
  • fastjson: 1.1.8
  • zookeeper: 3.3.3
  • jedis: 2.0.0
  • xmemcached: 1.3.6
  • jfreechart: 1.0.13
  • hessian: 4.0.7
  • jetty: 6.1.26
  • hibernate-validator: 4.2.0.Final
  • zkclient: 0.1
  • curator: 1.1.10
  • cxf: 2.6.1
  • thrift: 0.8.0

JEE:

  • servlet: 2.5
  • bsf: 3.1
  • validation-api: 1.0.0.GA
  • jcache: 0.4

成熟度

(+) (#)

功能成熟度

(#)

Feature Maturity Strength Problem Advise User
併發控制 Tested 併發控制   試用  
鏈接控制 Tested 鏈接數控制   試用  
直連提供者 Tested 點對點直連服務提供方,用於測試   測試環境使用 Alibaba
分組聚合 Tested 分組聚合返回值,用於菜單聚合等服務 特殊場景使用 可用於生產環境  
參數驗證 Tested 參數驗證,JSR303驗證框架集成 對性能有影響 試用 LaiWang
結果緩存 Tested 結果緩存,用於加速請求   試用  
泛化引用 Stable 泛化調用,無需業務接口類進行遠程調用,用於測試平臺,開放網關橋接等   可用於生產環境 Alibaba
泛化實現 Stable 泛化實現,無需業務接口類實現任意接口,用於Mock平臺   可用於生產環境 Alibaba
回聲測試 Tested 回聲測試   試用  
隱式傳參 Stable 附加參數   可用於生產環境  
異步調用 Tested 不可靠異步調用   試用  
本地調用 Tested 本地調用   試用  
參數回調 Tested 參數回調 特殊場景使用 試用 Registry
事件通知 Tested 事件通知,在遠程調用執行先後觸發   試用  
本地存根 Stable 在客戶端執行部分邏輯   可用於生產環境 Alibaba
本地假裝 Stable 僞造返回結果,可在失敗時執行,或直接執行,用於服務降級 需註冊中心支持 可用於生產環境 Alibaba
延遲暴露 Stable 延遲暴露服務,用於等待應用加載warmup數據,或等待spring加載完成   可用於生產環境 Alibaba
延遲鏈接 Tested 延遲創建鏈接,調用時創建   試用 Registry
粘滯鏈接 Tested 粘滯鏈接,老是向同一個提供方發起請求,除非此提供方掛掉,再切換到另外一臺   試用 Registry
令牌驗證 Tested 令牌驗證,用於服務受權 需註冊中心支持 試用  
路由規則 Tested 動態決定調用關係 需註冊中心支持 試用  
配置規則 Tested 動態下發配置,實現功能的開關 需註冊中心支持 試用  
訪問日誌 Tested 訪問日誌,用於記錄調用信息 本地存儲,影響性能,受磁盤大小限制 試用  
分佈式事務 Research JTA/XA三階段提交事務 不穩定 不可用  

策略成熟度

(#)

Feature Maturity Strength Problem Advise User
Zookeeper註冊中心 Stable 支持基於網絡的集羣方式,有普遍周邊開源產品,建議使用dubbo-2.3.3以上版本(推薦使用) 依賴於Zookeeper的穩定性 可用於生產環境  
Redis註冊中心 Stable 支持基於客戶端雙寫的集羣方式,性能高 要求服務器時間同步,用於檢查心跳過時髒數據 可用於生產環境  
Multicast註冊中心 Tested 去中心化,不須要安裝註冊中心 依賴於網絡拓普和路由,跨機房有風險 小規模應用或開發測試環境  
Simple註冊中心 Tested Dogfooding,註冊中心自己也是一個標準的RPC服務 沒有集羣支持,可能單點故障 試用  
Feature Maturity Strength Problem Advise User
Simple監控中心 Stable 支持JFreeChart統計報表 沒有集羣支持,可能單點故障,但故障後不影響RPC運行 可用於生產環境  
Feature Maturity Strength Problem Advise User
Dubbo協議 Stable 採用NIO複用單一長鏈接,並使用線程池併發處理請求,減小握手和加大併發效率,性能較好(推薦使用) 在大文件傳輸時,單一鏈接會成爲瓶頸 可用於生產環境 Alibaba
Rmi協議 Stable 可與原生RMI互操做,基於TCP協議 偶爾會鏈接失敗,需重建Stub 可用於生產環境 Alibaba
Hessian協議 Stable 可與原生Hessian互操做,基於HTTP協議 需hessian.jar支持,http短鏈接的開銷大 可用於生產環境  
Feature Maturity Strength Problem Advise User
Netty Transporter Stable JBoss的NIO框架,性能較好(推薦使用) 一次請求派發兩種事件,需屏蔽無用事件 可用於生產環境 Alibaba
Mina Transporter Stable 老牌NIO框架,穩定 待發送消息隊列派發不及時,大壓力下,會出現FullGC 可用於生產環境 Alibaba
Grizzly Transporter Tested Sun的NIO框架,應用於GlassFish服務器中 線程池不可擴展,Filter不能攔截下一Filter 試用  
Feature Maturity Strength Problem Advise User
Hessian Serialization Stable 性能較好,多語言支持(推薦使用) Hessian的各版本兼容性很差,可能和應用使用的Hessian衝突,Dubbo內嵌了hessian3.2.1的源碼 可用於生產環境 Alibaba
Dubbo Serialization Tested 經過不傳送POJO的類元信息,在大量POJO傳輸時,性能較好 當參數對象增長字段時,需外部文件聲明 試用  
Json Serialization Tested 純文本,可跨語言解析,缺省採用FastJson解析 性能較差 試用  
Java Serialization Stable Java原生支持 性能較差 可用於生產環境  
Feature Maturity Strength Problem Advise User
Javassist ProxyFactory Stable 經過字節碼生成代替反射,性能比較好(推薦使用) 依賴於javassist.jar包,佔用JVM的Perm內存,Perm可能要設大一些:java -XX:PermSize=128m 可用於生產環境 Alibaba
Jdk ProxyFactory Stable JDK原生支持 性能較差 可用於生產環境  
Feature Maturity Strength Problem Advise User
Failover Cluster Stable 失敗自動切換,當出現失敗,重試其它服務器,一般用於讀操做(推薦使用) 重試會帶來更長延遲 可用於生產環境 Alibaba
Failfast Cluster Stable 快速失敗,只發起一次調用,失敗當即報錯,一般用於非冪等性的寫操做 若是有機器正在重啓,可能會出現調用失敗 可用於生產環境 Alibaba
Failsafe Cluster Stable 失敗安全,出現異常時,直接忽略,一般用於寫入審計日誌等操做 調用信息丟失 可用於生產環境 Monitor
Failback Cluster Tested 失敗自動恢復,後臺記錄失敗請求,定時重發,一般用於消息通知操做 不可靠,重啓丟失 可用於生產環境 Registry
Forking Cluster Tested 並行調用多個服務器,只要一個成功即返回,一般用於實時性要求較高的讀操做 須要浪費更多服務資源 可用於生產環境  
Broadcast Cluster Tested 廣播調用全部提供者,逐個調用,任意一臺報錯則報錯,一般用於更新提供方本地狀態 速度慢,任意一臺報錯則報錯 可用於生產環境  
Feature Maturity Strength Problem Advise User
Random LoadBalance Stable 隨機,按權重設置隨機機率(推薦使用) 在一個截面上碰撞的機率高,重試時,可能出現瞬間壓力不均 可用於生產環境 Alibaba
RoundRobin LoadBalance Stable 輪循,按公約後的權重設置輪循比率 存在慢的機器累積請求問題,極端狀況可能產生雪崩 可用於生產環境  
LeastActive LoadBalance Stable 最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差,使慢的機器收到更少請求 不支持權重,在容量規劃時,不能經過權重把壓力導向一臺機器壓測容量 可用於生產環境  
ConsistentHash LoadBalance Stable 一致性Hash,相同參數的請求老是發到同一提供者,當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更 壓力分攤不均 可用於生產環境  
Feature Maturity Strength Problem Advise User
條件路由規則 Stable 基於條件表達式的路由規則,功能簡單易用 有些複雜多分支條件狀況,規則很難描述 可用於生產環境 Alibaba
腳本路由規則 Tested 基於腳本引擎的路由規則,功能強大 沒有運行沙箱,腳本能力過於強大,可能成爲後門 試用  
Feature Maturity Strength Problem Advise User
Spring Container Stable 自動加載META-INF/spring目錄下的全部Spring配置   可用於生產環境 Alibaba
Jetty Container Stable 啓動一個內嵌Jetty,用於彙報狀態 大量訪問頁面時,會影響服務器的線程和內存 可用於生產環境 Alibaba
Log4j Container Stable 自動配置log4j的配置,在多進程啓動時,自動給日誌文件按進程分目錄 用戶不能控制log4j的配置,不靈活 可用於生產環境 Alibaba

配置

(+) (#)

Xml配置

(+) (#)

配置項說明
詳細配置項,請參見:配置參考手冊 (+)
API使用說明
若是不想使用Spring配置,而但願經過API的方式進行調用,請參見:API配置 (+)
配置使用說明
想知道如何使用配置,請參見:快速啓動 (+)

示例:

provider.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
     xsi:schemaLocation = "http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
 
     < dubbo:application name = "hello-world-app"  />
 
     < dubbo:registry address = "multicast://224.5.6.7:1234" />
 
     < dubbo:protocol name = "dubbo" port = "20880" />
 
     < dubbo:service interface = "com.alibaba.dubbo.demo.DemoService" ref = "demoServiceLocal" />
 
     < dubbo:reference id = "demoServiceRemote" interface = "com.alibaba.dubbo.demo.DemoService" />
 
</ beans >
全部標籤者支持自定義參數,用於不一樣擴展點實現的特殊配置。

如:

< dubbo:protocol name = "jms" >
     < dubbo:parameter key = "queue" value = "http://10.20.160.198/wiki/display/dubbo/10.20.31.22" />
</ dubbo:protocol >

或:(2.1.0開始支持)

注意聲明:xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation = "http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
 
     < dubbo:protocol name = "jms" p:queue = "http://10.20.160.198/wiki/display/dubbo/10.20.31.22" />
 
</ beans >

Configuration Relation:

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

Configuration Override:

  • 上圖中以timeout爲例,顯示了配置的查找順序,其它retries, loadbalance, actives等相似。
    • 方法級優先,接口級次之,全局配置再次之。
    • 若是級別同樣,則消費方優先,提供方次之。
  • 其中,服務提供方配置,經過URL經由註冊中心傳遞給消費方。
  • 建議由服務提供方設置超時,由於一個方法須要執行多長時間,服務提供方更清楚,若是一個消費方同時引用多個服務,就不須要關心每一個服務的超時設置。
  • 理論上ReferenceConfig的非服務標識配置,在ConsumerConfig,ServiceConfig, ProviderConfig都可以缺省配置。

屬性配置

(+) (#)

若是公共配置很簡單,沒有多註冊中心,多協議等狀況,或者想多個Spring容器想共享配置,能夠使用dubbo.properties做爲缺省配置。
Dubbo將自動加載classpath根目錄下的dubbo.properties,能夠經過JVM啓動參數:-Ddubbo.properties.file=xxx.properties 改變缺省配置位置。
若是classpath根目錄下存在多個dubbo.properties,好比多個jar包中有dubbo.properties,Dubbo會任意加載,並打印Error日誌,後續可能改成拋異常。

映射規則:

  • 將XML配置的標籤名,加屬性名,用點分隔,多個屬性拆成多行:
    • 好比:dubbo.application.name=foo等價於<dubbo:application name="foo" />
    • 好比:dubbo.registry.address=10.20.153.10:9090等價於<dubbo:registry address="10.20.153.10:9090" />
  • 若是XML有多行同名標籤配置,可用id號區分,若是沒有id號將對全部同名標籤生效:
    • 好比:dubbo.protocol.rmi.port=1234等價於<dubbo:protocol id="rmi" name="rmi" port="1099" /> (協議的id沒配時,缺省使用協議名做爲id)
    • 好比:dubbo.registry.china.address=10.20.153.10:9090等價於<dubbo:registry id="china" address="10.20.153.10:9090" />

典型配置如:

dubbo.properties
dubbo.application.name=foo
dubbo.application.owner=bar
dubbo.registry.address= 10.20 . 153.10 : 9090

覆蓋策略:

  • JVM啓動-D參數優先,這樣能夠使用戶在部署和啓動時進行參數重寫,好比在啓動時需改變協議的端口。
  • XML次之,若是在XML中有配置,則dubbo.properties中的相應配置項無效。
  • Properties最後,至關於缺省值,只有XML沒有配置時,dubbo.properties的相應配置項纔會生效,一般用於共享公共配置,好比應用名。

註解配置

(+) (#)

2.2.1以上版本支持

服務提供方註解:

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

服務提供方配置:

<!-- 公共信息,也能夠用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;
 
}

服務消費方配置:

<!-- 公共信息,也能夠用dubbo.properties配置 -->
< dubbo:application name = "annotation-consumer" />
< dubbo:registry address = "127.0.0.1:4548" />
 
<!-- 掃描註解包路徑,多個包用逗號分隔,不填pacakge表示掃描當前ApplicationContext中全部的類 -->
< dubbo:annotation package = "com.foo.bar.action" />

也能夠使用:(等價於前面的:<dubbo:annotation package="com.foo.bar.service" />)

< 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 >
Spring2.5及之後版本支持component-scan,若是用的是Spring2.0及之前版本,需配置:
<!-- Spring2.0支持@Service註解配置,但不支持package屬性自動加載bean的實例,需人工定義bean的實例。-->
< dubbo:annotation />
< bean id = "barService" class = "com.foo.BarServiceImpl" />

API配置

(+) (#)

API使用範圍
API僅用於OpenAPI, ESB, Test, Mock等系統集成,普通服務提供方或消費方,請採用配置方式使用Dubbo,請參見:Xml配置 (+)
API屬性含義參考
API屬性與配置項一對一,各屬性含義,請參見:配置參考手冊 (+),
好比:ApplicationConfig.setName("xxx") 對應 <dubbo:application name="xxx" />

(1) 服務提供者:

import com.alibaba.dubbo.rpc.config.ApplicationConfig;
import com.alibaba.dubbo.rpc.config.RegistryConfig;
import com.alibaba.dubbo.rpc.config.ProviderConfig;
import com.alibaba.dubbo.rpc.config.ServiceConfig;
import com.xxx.XxxService;
import com.xxx.XxxServiceImpl;
 
// 服務實現
XxxService xxxService = new XxxServiceImpl();
 
// 當前應用配置
ApplicationConfig application = new ApplicationConfig();
application.setName( "xxx" );
 
// 鏈接註冊中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress( "10.20.130.230:9090" );
registry.setUsername( "aaa" );
registry.setPassword( "bbb" );
 
// 服務提供者協議配置
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName( "dubbo" );
protocol.setPort( 12345 );
protocol.setThreads( 200 );
 
// 注意:ServiceConfig爲重對象,內部封裝了與註冊中心的鏈接,以及開啓服務端口
 
// 服務提供者暴露服務配置
ServiceConfig<XxxService> service = new ServiceConfig<XxxService>(); // 此實例很重,封裝了與註冊中心的鏈接,請自行緩存,不然可能形成內存和鏈接泄漏
service.setApplication(application);
service.setRegistry(registry); // 多個註冊中心能夠用setRegistries()
service.setProtocol(protocol); // 多個協議能夠用setProtocols()
service.setInterface(XxxService. class );
service.setRef(xxxService);
service.setVersion( "1.0.0" );
 
// 暴露及註冊服務
service.export();

(2) 服務消費者:

import com.alibaba.dubbo.rpc.config.ApplicationConfig;
import com.alibaba.dubbo.rpc.config.RegistryConfig;
import com.alibaba.dubbo.rpc.config.ConsumerConfig;
import com.alibaba.dubbo.rpc.config.ReferenceConfig;
import com.xxx.XxxService;
 
// 當前應用配置
ApplicationConfig application = new ApplicationConfig();
application.setName( "yyy" );
 
// 鏈接註冊中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress( "10.20.130.230:9090" );
registry.setUsername( "aaa" );
registry.setPassword( "bbb" );
 
// 注意:ReferenceConfig爲重對象,內部封裝了與註冊中心的鏈接,以及與服務提供方的鏈接
 
// 引用遠程服務
ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>(); // 此實例很重,封裝了與註冊中心的鏈接以及與提供者的鏈接,請自行緩存,不然可能形成內存和鏈接泄漏
reference.setApplication(application);
reference.setRegistry(registry); // 多個註冊中心能夠用setRegistries()
reference.setInterface(XxxService. class );
reference.setVersion( "1.0.0" );
 
// 和本地bean同樣使用xxxService
XxxService xxxService = reference.get(); // 注意:此代理對象內部封裝了全部通信細節,對象較重,請緩存複用

(3) 特殊場景

注:下面只列出不一樣的地方,其它參見上面的寫法

(3.1) 方法級設置:

...
 
// 方法級配置
List<MethodConfig> methods = new ArrayList<MethodConfig>();
MethodConfig method = new MethodConfig();
method.setName( "createXxx" );
method.setTimeout( 10000 );
method.setRetries( 0 );
methods.add(method);
 
// 引用遠程服務
ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>(); // 此實例很重,封裝了與註冊中心的鏈接以及與提供者的鏈接,請自行緩存,不然可能形成內存和鏈接泄漏
...
reference.setMethods(methods); // 設置方法級配置
 
...

(3.2) 點對點直連:

...
 
ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>(); // 此實例很重,封裝了與註冊中心的鏈接以及與提供者的鏈接,請自行緩存,不然可能形成內存和鏈接泄漏
// 若是點對點直連,能夠用reference.setUrl()指定目標地址,設置url後將繞過註冊中心,
// 其中,協議對應provider.setProtocol()的值,端口對應provider.setPort()的值,
// 路徑對應service.setPath()的值,若是未設置path,缺省path爲接口名
reference.setUrl( "dubbo://10.20.130.230:20880/com.xxx.XxxService" );
 
...

示例

(+) (#)

想完整的運行起來,請參見:快速啓動 (+),這裏只列出各類場景的配置方式
如下示例所有使用基於Spring的Xml配置 (+)做爲參考,若是不想使用Spring,而但願經過API的方式進行調用,請參見:API配置 (+)

啓動時檢查

(+) (#)

Dubbo缺省會在啓動時檢查依賴的服務是否可用,不可用時會拋出異常,阻止Spring初始化完成,以便上線時,能及早發現問題,默認check=true。
若是你的Spring容器是懶加載的,或者經過API編程延遲引用服務,請關閉check,不然服務臨時不可用時,會拋出異常,拿到null引用,若是check=false,老是會返回引用,當服務恢復時,能自動連上。

能夠經過check="false"關閉檢查,好比,測試時,有些服務不關心,或者出現了循環依賴,必須有一方先啓動。

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

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

關閉全部服務的啓動時檢查:(沒有提供者時報錯)

< dubbo:consumer check = "false" />

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

< dubbo:registry check = "false" />

也能夠用dubbo.properties配置:

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.consumer.check=false,是設置check的缺省值,若是配置中有顯式的聲明,如:<dubbo:reference check="true"/>,不會受影響。
  • dubbo.registry.check=false,前面兩個都是指訂閱成功,但提供者列表是否爲空是否報錯,若是註冊訂閱失敗時,也容許啓動,需使用此選項,將在後臺定時重試。

引用缺省是延遲初始化的,只有引用被注入到其它Bean,或被getBean()獲取,纔會初始化。
若是須要飢餓加載,即沒有人引用也當即生成動態代理,能夠配置:

< dubbo:reference interface = "com.foo.BarService" init = "true" />

集羣容錯

(+) (#)

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

各節點關係:

  • 這裏的Invoker是Provider的一個可調用Service的抽象,Invoker封裝了Provider地址及Service接口信息。
  • Directory表明多個Invoker,能夠把它當作List<Invoker>,但與List不一樣的是,它的值多是動態變化的,好比註冊中心推送變動。
  • Cluster將Directory中的多個Invoker假裝成一個Invoker,對上層透明,假裝過程包含了容錯邏輯,調用失敗後,重試另外一個。
  • Router負責從多個Invoker中按路由規則選出子集,好比讀寫分離,應用隔離等。
  • LoadBalance負責從多個Invoker中選出具體的一個用於本次調用,選的過程包含了負載均衡算法,調用失敗後,須要重選。
集羣容錯模式:

能夠自行擴展集羣容錯策略,參見:集羣擴展

Failover Cluster
  • 失敗自動切換,當出現失敗,重試其它服務器。(缺省)
  • 一般用於讀操做,但重試會帶來更長延遲。
  • 可經過retries="2"來設置重試次數(不含第一次)。
Failfast Cluster
  • 快速失敗,只發起一次調用,失敗當即報錯。
  • 一般用於非冪等性的寫操做,好比新增記錄。
Failsafe Cluster
  • 失敗安全,出現異常時,直接忽略。
  • 一般用於寫入審計日誌等操做。
Failback Cluster
  • 失敗自動恢復,後臺記錄失敗請求,定時重發。
  • 一般用於消息通知操做。
Forking Cluster
  • 並行調用多個服務器,只要一個成功即返回。
  • 一般用於實時性要求較高的讀操做,但須要浪費更多服務資源。
  • 可經過forks="2"來設置最大並行數。
Broadcast Cluster
  • 廣播調用全部提供者,逐個調用,任意一臺報錯則報錯。(2.1.0開始支持)
  • 一般用於通知全部提供者更新緩存或日誌等本地資源信息。

重試次數配置如:(failover集羣模式生效)

< dubbo:service retries = "2" />

或:

< dubbo:reference retries = "2" />

或:

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

集羣模式配置如:

< dubbo:service cluster = "failsafe" />

或:

< dubbo:reference cluster = "failsafe" />

負載均衡

(+) (#)

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

能夠自行擴展負載均衡策略,參見:負載均衡擴展

Random LoadBalance
  • 隨機,按權重設置隨機機率。
  • 在一個截面上碰撞的機率高,但調用量越大分佈越均勻,並且按機率使用權重後也比較均勻,有利於動態調整提供者權重。
RoundRobin LoadBalance
  • 輪循,按公約後的權重設置輪循比率。
  • 存在慢的提供者累積請求問題,好比:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,長此以往,全部請求都卡在調到第二臺上。
LeastActive LoadBalance
  • 最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差。
  • 使慢的提供者收到更少請求,由於越慢的提供者的調用先後計數差會越大。
ConsistentHash LoadBalance
  • 一致性Hash,相同參數的請求老是發到同一提供者。
  • 當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更。
  • 算法參見:http://en.wikipedia.org/wiki/Consistent_hashing
  • 缺省只對第一個參數Hash,若是要修改,請配置<dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用160份虛擬節點,若是要修改,請配置<dubbo:parameter key="hash.nodes" value="320" />

配置如:

< 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 >

線程模型

(+) (#)

事件處理線程說明
  • 若是事件處理的邏輯能迅速完成,而且不會發起新的IO請求,好比只是在內存中記個標識,則直接在IO線程上處理更快,由於減小了線程池調度。
  • 但若是事件處理邏輯較慢,或者須要發起新的IO請求,好比須要查詢數據庫,則必須派發到線程池,不然IO線程阻塞,將致使不能接收其它請求。
  • 若是用IO線程處理事件,又在事件處理過程當中發起新的IO請求,好比在鏈接事件中發起登陸請求,會報「可能引起死鎖」異常,但不會真死鎖。
  • Dispatcher
    • all 全部消息都派發到線程池,包括請求,響應,鏈接事件,斷開事件,心跳等。
    • direct 全部消息都不派發到線程池,所有在IO線程上直接執行。
    • message 只有請求響應消息派發到線程池,其它鏈接斷開事件,心跳等消息,直接在IO線程上執行。
    • execution 只請求消息派發到線程池,不含響應,響應和其它鏈接斷開事件,心跳等消息,直接在IO線程上執行。
    • connection 在IO線程上,將鏈接斷開事件放入隊列,有序逐個執行,其它消息派發到線程池。
  • ThreadPool
    • fixed 固定大小線程池,啓動時創建線程,不關閉,一直持有。(缺省)
    • cached 緩存線程池,空閒一分鐘自動刪除,須要時重建。
    • limited 可伸縮線程池,但池中的線程數只會增加不會收縮。(爲避免收縮時忽然來了大流量引發的性能問題)。

配置如:

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

直連提供者

(+) (#)

在開發及測試環境下,常常須要繞過註冊中心,只測試指定服務提供者,這時候可能須要點對點直連,
點對點直聯方式,將以服務接口爲單位,忽略註冊中心的提供者列表,
A接口配置點對點,不影響B接口從註冊中心獲取列表。

(1) 若是是線上需求須要點對點,可在<dubbo:reference>中配置url指向提供者,將繞過註冊中心,多個地址用分號隔開,配置以下:(1.0.6及以上版本支持)

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

(2) 在JVM啓動參數中加入-D參數映射服務地址,如:
(key爲服務名,value爲服務提供者url,此配置優先級最高,1.0.15及以上版本支持)

java -Dcom.alibaba.xxx.XxxService=dubbo: //localhost:20890
注意
爲了不復雜化線上環境,不要在線上使用這個功能,只應在測試階段使用。

(3) 若是服務比較多,也能夠用文件映射,如:
(用-Ddubbo.resolve.file指定映射文件路徑,此配置優先級高於<dubbo:reference>中的配置,1.0.15及以上版本支持)
(2.0以上版本自動加載${user.home}/dubbo-resolve.properties文件,不須要配置)

java -Ddubbo.resolve.file=xxx.properties

而後在映射文件xxx.properties中加入:
(key爲服務名,value爲服務提供者url)

com.alibaba.xxx.XxxService=dubbo: //localhost:20890
注意
爲了不復雜化線上環境,不要在線上使用這個功能,只應在測試階段使用。

只訂閱

(+) (#)

問題
爲方便開發測試,常常會在線下共用一個全部服務可用的註冊中心,這時,若是一個正在開發中的服務提供者註冊,可能會影響消費者不能正常運行。
解決方案
可讓服務提供者開發方,只訂閱服務(開發的服務可能依賴其它服務),而不註冊正在開發的服務,經過直連測試正在開發的服務。

禁用註冊配置:

< 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" />

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

若是是一個第三方獨立提供者,好比memcached等,能夠直接向註冊中心寫入提供者地址信息,消費者正常使用:
(一般由腳本監控中心頁面等調用)

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo" ));

多協議

(+) (#)

能夠自行擴展協議,參見:協議擴展

(1) 不一樣服務不一樣協議

好比:不一樣服務在性能上適用不一樣協議進行傳輸,好比大數據用短鏈接協議,小數據大併發用長鏈接協議。

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
     < dubbo:registry id = "registry" address = "10.20.141.150:9090" username = "admin" password = "hello1234" />
 
     <!-- 多協議配置 -->
     < dubbo:protocol name = "dubbo" port = "20880" />
     < dubbo:protocol name = "rmi" port = "1099" />
 
     <!-- 使用dubbo協議暴露服務 -->
     < dubbo:service interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" ref = "helloService" protocol = "dubbo" />
     <!-- 使用rmi協議暴露服務 -->
     < dubbo:service interface = "com.alibaba.hello.api.DemoService" version = "1.0.0" ref = "demoService" protocol = "rmi" />
 
</ beans >

(2) 多協議暴露服務

好比:須要與http客戶端互操做

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
     < dubbo:registry id = "registry" address = "10.20.141.150:9090" username = "admin" password = "hello1234" />
 
     <!-- 多協議配置 -->
     < dubbo:protocol name = "dubbo" port = "20880" />
     < dubbo:protocol name = "hessian" port = "8080" />
 
     <!-- 使用多個協議暴露服務 -->
     < dubbo:service id = "helloService" interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" protocol = "dubbo,hessian" />
 
</ beans >

多註冊中心

(+) (#)

能夠自行擴展註冊中心,參見:註冊中心擴展

(1) 多註冊中心註冊

好比:中文站有些服務來不及在青島部署,只在杭州部署,而青島的其它應用須要引用此服務,就能夠將服務同時註冊到兩個註冊中心。

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
 
     <!-- 多註冊中心配置 -->
     < 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" />
 
</ beans >

(2) 不一樣服務使用不一樣註冊中心

好比:CRM有些服務是專門爲國際站設計的,有些服務是專門爲中文站設計的。

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
 
     <!-- 多註冊中心配置 -->
     < dubbo:registry id = "chinaRegistry" address = "10.20.141.150:9090" />
     < dubbo:registry id = "intlRegistry" address = "10.20.154.177:9010" default = "false" />
 
     <!-- 向中文站註冊中心註冊 -->
     < dubbo:service interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" ref = "helloService" registry = "chinaRegistry" />
 
     <!-- 向國際站註冊中心註冊 -->
     < dubbo:service interface = "com.alibaba.hello.api.DemoService" version = "1.0.0" ref = "demoService" registry = "intlRegistry" />
 
</ beans >

(3) 多註冊中心引用

好比:CRM需同時調用中文站和國際站的PC2服務,PC2在中文站和國際站均有部署,接口及版本號都同樣,但連的數據庫不同。

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
 
     <!-- 多註冊中心配置 -->
     < 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.HelloService" version = "1.0.0" registry = "chinaRegistry" />
 
     <!-- 引用國際站站服務 -->
     < dubbo:reference id = "intlHelloService" interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" registry = "intlRegistry" />
 
</ beans >

若是隻是測試環境臨時須要鏈接兩個不一樣註冊中心,使用豎號分隔多個不一樣註冊中心地址:

consumer.xml
<? xml version = "1.0" encoding = "UTF-8" ?>
 
     < dubbo:application name = "world"  />
 
     <!-- 多註冊中心配置,豎號分隔表示同時鏈接多個不一樣註冊中心,同一註冊中心的多個集羣地址用逗號分隔 -->
     < 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" />
 
</ beans >

服務分組

(+) (#)

當一個接口有多種實現時,能夠用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.IndexService" />

任意組:(2.2.0以上版本支持,老是隻調一個可用組的實現)

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

多版本

(+) (#)

當一個接口實現,出現不兼容升級時,能夠用版本號過渡,版本號不一樣的服務相互間不引用。
  • 在低壓力時間段,先升級一半提供者爲新版本
  • 再將全部消費者升級爲新版本
  • 而後將剩下的一半提供者升級爲新版本
< 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" />

不區分版本:(2.2.0以上版本支持)

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

分組聚合

(+) (#)

按組合並返回結果,好比菜單服務,接口同樣,但有多種實現,用group區分,如今消費方需從每種group中調用一次返回結果,合併結果返回,這樣就能夠實現聚合菜單項。
從2.1.0版本開始支持

代碼參見:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge

配置如:(搜索全部分組)

< 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 >

參數驗證

(+) (#)

參數驗證功能是基於JSR303實現的,用戶只需標識JSR303標準的驗證Annotation,並經過聲明filter來實現驗證。
2.1.0以上版本支持

完整示例代碼參見:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation

驗證方式可擴展,參見:Validation擴展點

參數標註示例:

import java.io.Serializable;
import java.util.Date;
 
import javax.validation.constraints.Future;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
 
public class ValidationParameter implements Serializable {
     
     private static final long serialVersionUID = 7158911668568000392L;
 
     @NotNull // 不容許爲空
     @Size (min = 1 , max = 20 ) // 長度或大小範圍
     private String name;
 
     @NotNull (groups = ValidationService.Save. class ) // 保存時不容許爲空,更新時容許爲空 ,表示不更新該字段
     @Pattern (regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$" )
     private String email;
 
     @Min ( 18 ) // 最小值
     @Max ( 100 ) // 最大值
     private int age;
 
     @Past // 必須爲一個過去的時間
     private Date loginDate;
 
     @Future // 必須爲一個將來的時間
     private Date expiryDate;
 
     public String getName() {
         return name;
     }
 
     public void setName(String name) {
         this .name = name;
     }
 
     public String getEmail() {
         return email;
     }
 
     public void setEmail(String email) {
         this .email = email;
     }
 
     public int getAge() {
         return age;
     }
 
     public void setAge( int age) {
         this .age = age;
     }
 
     public Date getLoginDate() {
         return loginDate;
     }
 
     public void setLoginDate(Date loginDate) {
         this .loginDate = loginDate;
     }
 
     public Date getExpiryDate() {
         return expiryDate;
     }
 
     public void setExpiryDate(Date expiryDate) {
         this .expiryDate = expiryDate;
     }
 
}

分組驗證示例:

public interface ValidationService { // 缺省可按服務接口區分驗證場景,如:@NotNull(groups = ValidationService.class)
     
     @interface Save{} // 與方法同名接口,首字母大寫,用於區分驗證場景,如:@NotNull(groups = ValidationService.Save.class),可選
     void save(ValidationParameter parameter);
 
     void update(ValidationParameter parameter);
 
}

關聯驗證示例:

import javax.validation.GroupSequence;
 
public interface ValidationService {
     
     @GroupSequence (Update. class ) // 同時驗證Update組規則
     @interface Save{}
     void save(ValidationParameter parameter);
 
     @interface Update{}
     void update(ValidationParameter parameter);
 
}

參數驗證示例:

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
 
public interface ValidationService {
 
     void save( @NotNull ValidationParameter parameter); // 驗證參數不爲空
 
     void delete( @Min ( 1 ) int id); // 直接對基本類型參數驗證
 
}

在客戶端驗證參數:

< dubbo:reference id = "validationService" interface = "com.alibaba.dubbo.examples.validation.api.ValidationService" validation = "true" />

在服務器端驗證參數:

< dubbo:service interface = "com.alibaba.dubbo.examples.validation.api.ValidationService" ref = "validationService" validation = "true" />

驗證異常信息:

import javax.validation.ConstraintViolationException;
import javax.validation.ConstraintViolationException;
 
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.alibaba.dubbo.examples.validation.api.ValidationParameter;
import com.alibaba.dubbo.examples.validation.api.ValidationService;
import com.alibaba.dubbo.rpc.RpcException;
 
public class ValidationConsumer {
     
     public static void main(String[] args) throws Exception {
         String config = ValidationConsumer. class .getPackage().getName().replace( '.' , '/' ) + "/validation-consumer.xml" ;
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
         context.start();
         ValidationService validationService = (ValidationService)context.getBean( "validationService" );
         // Error
         try {
             parameter = new ValidationParameter();
             validationService.save(parameter);
             System.out.println( "Validation ERROR" );
         } catch (RpcException e) { // 拋出的是RpcException
             ConstraintViolationException ve = (ConstraintViolationException) e.getCause(); // 裏面嵌了一個ConstraintViolationException
             Set<ConstraintViolation<?>> violations = ve.getConstraintViolations(); // 能夠拿到一個驗證錯誤詳細信息的集合
             System.out.println(violations);
         }
     }
 
}

須要加入依賴:

< dependency >
     < groupId >javax.validation</ groupId >
     < artifactId >validation-api</ artifactId >
     < version >1.0.0.GA</ version >
</ dependency >
< dependency >
     < groupId >org.hibernate</ groupId >
     < artifactId >hibernate-validator</ artifactId >
     < version >4.2.0.Final</ version >
</ dependency >

結果緩存

(+) (#)

結果緩存,用於加速熱門數據的訪問速度,Dubbo提供聲明式緩存,以減小用戶加緩存的工做量。
2.1.0以上版本支持

示例代碼:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache

  • lru 基於最近最少使用原則刪除多餘緩存,保持最熱的數據被緩存。
  • threadlocal 當前線程緩存,好比一個頁面渲染,用到不少portal,每一個portal都要去查用戶信息,經過線程緩存,能夠減小這種多餘訪問。
  • jcache 與JSR107集成,能夠橋接各類緩存實現。

緩存類型可擴展,參見:CacheFactory擴展點

配置如:

< dubbo:reference interface = "com.foo.BarService" cache = "lru" />

或:

< dubbo:reference interface = "com.foo.BarService" >
     < dubbo:method name = "findBar" cache = "lru" />
</ dubbo:reference >

泛化引用

(+) (#)

泛接口調用方式主要用於客戶端沒有API接口及模型類元的狀況,參數及返回值中的全部POJO均用Map表示,一般用於框架集成,好比:實現一個通用的服務測試框架,可經過GenericService調用全部服務實現。
< dubbo:reference id = "barService" interface = "com.foo.BarService" generic = "true" />
GenericService barService = (GenericService) applicationContext.getBean( "barService" );
Object result = barService.$invoke( "sayHello" , new String[] { "java.lang.String" }, new Object[] { "World" });
import com.alibaba.dubbo.rpc.service.GenericService;
...
 
// 引用遠程服務
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); // 該實例很重量,裏面封裝了全部與註冊中心及服務提供方鏈接,請緩存
reference.setInterface( "com.xxx.XxxService" ); // 弱類型接口名
reference.setVersion( "1.0.0" );
reference.setGeneric( true ); // 聲明爲泛化接口
 
GenericService genericService = reference.get(); // 用com.alibaba.dubbo.rpc.service.GenericService能夠替代全部接口引用
 
// 基本類型以及Date,List,Map等不須要轉換,直接調用
Object result = genericService.$invoke( "sayHello" , new String[] { "java.lang.String" }, new Object[] { "world" });
 
// 用Map表示POJO參數,若是返回值爲POJO也將自動轉成Map
Map<String, Object> person = new HashMap<String, Object>();
person.put( "name" , "xxx" );
person.put( "password" , "yyy" );
Object result = genericService.$invoke( "findPerson" , new String[]{ "com.xxx.Person" }, new Object[]{person}); // 若是返回POJO將自動轉成Map
 
...

假設存在POJO如:

package com.xxx;
public class PersonImpl implements Person {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this .password= password;
}
}

則POJO數據:

Person person = new PersonImpl();
person.setName( "xxx" );
person.setPassword( "yyy" );

可用下面Map表示:

Map<String, Object> map = new HashMap<String, Object>();
map.put( "class" , "com.xxx.PersonImpl" ); // 注意:若是參數類型是接口,或者List等丟失泛型,可經過class屬性指定類型。
map.put( "name" , "xxx" );
map.put( "password" , "yyy" );

泛化實現

(+) (#)

泛接口實現方式主要用於服務器端沒有API接口及模型類元的狀況,參數及返回值中的全部POJO均用Map表示,一般用於框架集成,好比:實現一個通用的遠程服務Mock框架,可經過實現GenericService接口處理全部服務請求。
< bean id = "genericService" class = "com.foo.MyGenericService" />
< dubbo:service interface = "com.foo.BarService" ref = "genericService" />
package com.foo;
public class MyGenericService implements GenericService {
 
     public Object $invoke(String methodName, String[] parameterTypes, Object[] args) throws GenericException {
         if ( "sayHello" .equals(methodName)) {
             return "Welcome " + args[ 0 ];
         }
     }
 
}
...
GenericService xxxService = new XxxGenericService(); // 用com.alibaba.dubbo.rpc.service.GenericService能夠替代全部接口實現
 
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>(); // 該實例很重量,裏面封裝了全部與註冊中心及服務提供方鏈接,請緩存
service.setInterface( "com.xxx.XxxService" ); // 弱類型接口名
service.setVersion( "1.0.0" );
service.setRef(xxxService); // 指向一個通用服務實現
 
// 暴露及註冊服務
service.export();

回聲測試

(+) (#)

回聲測試用於檢測服務是否可用,回聲測試按照正常請求流程執行,可以測試整個調用是否通暢,可用於監控。
全部服務自動實現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的參數,參見《配置項一覽表》中的「對應URL參數」一列。
注意
RpcContext是一個ThreadLocal的臨時狀態記錄器,當接收到RPC請求,或發起RPC請求時,RpcContext的狀態都會變化。
好比:A調B,B再調C,則B機器上,在B調C以前,RpcContext記錄的是A調B的信息,在B調C以後,RpcContext記錄的是B調C的信息。

(1) 服務消費方

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

(2) 服務提供方

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

隱式傳參

(+) (#)

注:path,group,version,dubbo,token,timeout幾個key有特殊處理,請使用其它key值。

(1) 服務消費方

RpcContext.getContext().setAttachment( "index" , "1" ); // 隱式傳參,後面的遠程調用都會隱式將這些參數發送到服務器端,相似cookie,用於框架集成,不建議常規業務使用
xxxService.xxx(); // 遠程調用
// ...

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

(2) 服務提供方

public class XxxServiceImpl implements XxxService {
 
     public void xxx() { // 服務方法實現
         String index = RpcContext.getContext().getAttachment( "index" ); // 獲取客戶端隱式傳入的參數,用於框架集成,不建議常規業務使用
         // ...
     }
 
}

異步調用

(+) (#)

基於NIO的非阻塞實現並行調用,客戶端不須要啓動多線程便可完成並行調用多個遠程服務,相對多線程開銷較小。
2.0.6及其以上版本支持

配置聲明:

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 >

調用代碼:

fooService.findFoo(fooId); // 此調用會當即返回null
Future<Foo> fooFuture = RpcContext.getContext().getFuture(); // 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future。
 
barService.findBar(barId); // 此調用會當即返回null
Future<Bar> barFuture = RpcContext.getContext().getFuture(); // 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future。
 
// 此時findFoo和findBar的請求同時在執行,客戶端不須要啓動多線程來支持並行,而是藉助NIO的非阻塞完成。
 
Foo foo = fooFuture.get(); // 若是foo已返回,直接拿到返回值,不然線程wait住,等待foo返回後,線程會被notify喚醒。
Bar bar = barFuture.get(); // 同理等待bar返回。
 
// 若是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" />

本地調用

(+) (#)

本地調用,使用了Injvm協議,是一個僞協議,它不開啓端口,不發起遠程調用,只在JVM內直接關聯,但執行Dubbo的Filter鏈。

Define injvm protocol:

< dubbo:protocol name = "injvm" />

Set default protocol:

< dubbo:provider protocol = "injvm" />

Set service protocol:

< dubbo:service protocol = "injvm" />

Use injvm first:

< dubbo:consumer injvm = "true" .../>
< dubbo:provider injvm = "true" .../>

< dubbo:reference injvm = "true" .../>
< dubbo:service injvm = "true" .../>
注意:服務暴露與服務引用都須要聲明injvm="true"

自動暴露、引用本地服務

從 dubbo 2.2.0 開始,每一個服務默認都會在本地暴露;在引用服務的時候,默認優先引用本地服務;若是但願引用遠程服務能夠使用一下配置強制引用遠程服務。

...
     < dubbo:reference ... scope = "remote" />
...

參數回調

(+) (#)

參數回調方式與調用本地callback或listener相同,只須要在Spring的配置文件中聲明哪一個參數是callback類型便可,Dubbo將基於長鏈接生成反向代理,這樣就能夠從服務器端調用客戶端邏輯。
2.0.6及其以上版本支持

代碼參見:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback

(1) 共享服務接口:

服務接口示例:

CallbackService.java
package com.callback;
 
public interface CallbackService {
     void addListener(String key, CallbackListener listener);
}
CallbackListener.java
package com.callback;
 
public interface CallbackListener {
     void changed(String msg);
}

(2) 服務提供者:

服務提供者接口實現示例:

CallbackServiceImpl.java
package com.callback.impl;
 
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
import com.callback.CallbackListener;
import com.callback.CallbackService;
 
public class CallbackServiceImpl implements CallbackService {
     
     private final Map<String, CallbackListener> listeners = new ConcurrentHashMap<String, CallbackListener>();
  
     public CallbackServiceImpl() {
         Thread t = new Thread( new Runnable() {
             public void run() {
                 while ( true ) {
                     try {
                         for (Map.Entry<String, CallbackListener> entry : listeners.entrySet()){
                            try {
                                entry.getValue().changed(getChanged(entry.getKey()));
                            } catch (Throwable t) {
                                listeners.remove(entry.getKey());
                            }
                         }
                         Thread.sleep( 5000 ); // 定時觸發變動通知
                     } catch (Throwable t) { // 防護容錯
                         t.printStackTrace();
                     }
                 }
             }
         });
         t.setDaemon( true );
         t.start();
     }
  
     public void addListener(String key, CallbackListener listener) {
         listeners.put(key, listener);
         listener.changed(getChanged(key)); // 發送變動通知
     }
     
     private String getChanged(String key) {
         return "Changed: " + new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( new Date());
     }
 
}

服務提供者配置示例:

< bean id = "callbackService" class = "com.callback.impl.CallbackServiceImpl" />
< dubbo:service interface = "com.callback.CallbackService" ref = "callbackService" connections = "1" callbacks = "1000" >
     < dubbo:method name = "addListener" >
         < dubbo:argument index = "1" callback = "true" />
         <!--也能夠經過指定類型的方式-->
         <!--<dubbo:argument type="com.demo.CallbackListener" callback="true" />-->
     </ dubbo:method >
</ dubbo:service >

(2) 服務消費者:

服務消費者配置示例:

consumer.xml
< dubbo:reference id = "callbackService" interface = "com.callback.CallbackService" />

服務消費者調用示例:

CallbackServiceTest.java
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "classpath:consumer.xml" );
context.start();
 
CallbackService callbackService = (CallbackService) context.getBean( "callbackService" );
 
callbackService.addListener( "http://10.20.160.198/wiki/display/dubbo/foo.bar" , new CallbackListener(){
     public void changed(String msg) {
         System.out.println( "callback1:" + msg);
     }
});

事件通知

(+) (#)

在調用以前,調用以後,出現異常時,會觸發oninvoke, onreturn, onthrow三個事件,能夠配置當事件發生時,通知哪一個類的哪一個方法。
支持版本:2.0.7以後

(1) 服務提供者與消費者共享服務接口:

IDemoService.java
interface IDemoService {
     public Person get( int id);
}

(2) 服務提供者實現:

DemoServiceImpl.java
class NormalDemoService implements IDemoService {
     public Person get( int id) {
         return new Person(id, "charles`son" , 4 );
     }
}

(3) 服務提供者配置:

provider.xml
< dubbo:application name = "rpc-callback-demo" />
< bean id = "demoService" class = "com.alibaba.dubbo.callback.implicit.NormalDemoService" />
< dubbo:service interface = "com.alibaba.dubbo.callback.implicit.IDemoService" ref = "demoService" version = "1.0.0" group = "cn" />

(4) 服務消費者Callback接口及實現:

Nofify.java
interface Nofify {
     public void onreturn(Person msg, Integer id);
     public void onthrow(Throwable ex, Integer id);
}
NofifyImpl.java
class NofifyImpl implements Nofify {
     public Map<Integer, Person>    ret    = new HashMap<Integer, Person>();
     public Map<Integer, Throwable> errors = new HashMap<Integer, Throwable>();
     public void onreturn(Person msg, Integer id) {
         System.out.println( "onreturn:" + msg);
         ret.put(id, msg);
     }
     public void onthrow(Throwable ex, Integer id) {
         errors.put(id, ex);
     }
}

(5) 服務消費者Callback接口及實現:

consumer.xml
< bean id = "demoCallback" class = "com.alibaba.dubbo.callback.implicit.NofifyImpl" />
< dubbo:reference id = "demoService" interface = "com.alibaba.dubbo.callback.implicit.IDemoService" version = "1.0.0" group = "cn" >
       < dubbo:method name = "get" async = "true" onreturn = "demoCallback.onreturn" onthrow = "demoCallback.onthrow" />
</ dubbo:reference >
注:
callback與async功能正交分解:
async=true,表示結果是否立刻返回.
onreturn 表示是否須要回調.

組合狀況:(async=false 默認)
異步回調模式:async=true onreturn="xxx"
同步回調模式:async=false onreturn="xxx"
異步無回調 :async=true
同步無回調 :async=false

(6) TEST CASE:

Test.java
IDemoService demoService = (IDemoService) context.getBean( "demoService" );
NofifyImpl notify = (NofifyImpl) context.getBean( "demoCallback" );
int requestId = 2 ;
Person ret = demoService.get(requestId);
Assert.assertEquals( null , ret);
//for Test:只是用來講明callback正常被調用,業務具體實現自行決定.
for ( int i = 0 ; i < 10 ; i++) {
     if (!notify.ret.containsKey(requestId)) {
         Thread.sleep( 200 );
     } else {
         break ;
     }
}
Assert.assertEquals(requestId, notify.ret.get(requestId).getId());

本地存根

(+) (#)

遠程服務後,客戶端一般只剩下接口,而實現全在服務器端,但提供方有些時候想在客戶端也執行部分邏輯,好比:作ThreadLocal緩存,提早驗證參數,調用失敗後僞造容錯數據等等,此時就須要在API中帶上Stub,客戶端生成Proxy實,會把Proxy經過構造函數傳給Stub,而後把Stub暴露組給用戶,Stub能夠決定要不要去調Proxy。
Stub必須有可傳入Proxy的構造函數。

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

Or:

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

api.jar:

com.foo.BarService
com.foo.BarServiceStub // 在API旁邊放一個Stub實現,它實現BarService接口,並有一個傳入遠程BarService實例的構造函數
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一般用於服務降級,好比某驗權服務,當服務提供方所有掛掉後,客戶端不拋出異常,而是經過Mock數據返回受權失敗。
Mock是Stub的一個子集,便於服務提供方在客戶端執行容錯邏輯,因常常須要在出現RpcException(好比網絡失敗,超時等)時進行容錯,而在出現業務異常(好比登陸用戶名密碼錯誤)時不須要容錯,若是用Stub,可能就須要捕獲並依賴RpcException類,而用Mock就能夠不依賴RpcException,由於它的約定就是隻有出現RpcException時才執行。
< dubbo:service interface = "com.foo.BarService" mock = "true" />

Or:

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

api.jar:

com.foo.BarService
com.foo.BarServiceMock // 在API旁邊放一個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:service interface = "com.foo.BarService" mock = "return null" />

延遲暴露

(+) (#)

若是你的服務須要Warmup時間,好比初始化緩存,等待相關資源就位等,能夠使用delay進行延遲暴露。

延遲5秒暴露服務:

< dubbo:service delay = "5000" />

延遲到Spring初始化完成後,再暴露服務:(基於Spring的ContextRefreshedEvent事件觸發暴露)

< dubbo:service delay = "-1" />
Spring2.x初始化死鎖問題
在Spring解析到<dubbo:service />時,就已經向外暴露了服務,而Spring還在接着初始化其它Bean。
若是這時有請求進來,而且服務的實現類裏有調用applicationContext.getBean()的用法。

1. 請求線程的applicationContext.getBean()調用,先同步singletonObjects判斷Bean是否存在,不存在就同步beanDefinitionMap進行初始化,並再次同步singletonObjects寫入Bean實例緩存。

2. 而Spring初始化線程,因不須要判斷Bean的存在,直接同步beanDefinitionMap進行初始化,並同步singletonObjects寫入Bean實例緩存。

這樣就致使getBean線程,先鎖singletonObjects,再鎖beanDefinitionMap,再次鎖singletonObjects。
而Spring初始化線程,先鎖beanDefinitionMap,再鎖singletonObjects。
反向鎖致使線程死鎖,不能提供服務,啓動不了。

規避辦法
1. 強烈建議不要在服務的實現類中有applicationContext.getBean()的調用,所有采用IoC注入的方式使用Spring的Bean。
2. 若是實在要調getBean(),能夠將Dubbo的配置放在Spring的最後加載。
3. 若是不想依賴配置順序,能夠使用<dubbo:provider deplay=」-1」 />,使Dubbo在Spring容器初始化完後,再暴露服務。
4. 若是大量使用getBean(),至關於已經把Spring退化爲工廠模式在用,能夠將Dubbo的服務隔離單獨的Spring容器。

併發控制

(+) (#)

限制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" />

Or:

< 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 >

Or:

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

若是<dubbo:service>和<dubbo:reference>都配了actives,<dubbo:reference>優先,參見:配置的覆蓋策略

Load Balance均衡:

配置服務的客戶端的loadbalance屬性爲leastactive,此Loadbalance會調用併發數最小的Provider(Consumer端併發數)。

< dubbo:reference interface = "com.foo.BarService" loadbalance = "leastactive" />

Or:

< dubbo:service interface = "com.foo.BarService" loadbalance = "leastactive" />

鏈接控制

(+) (#)

限制服務器端接受的鏈接不能超過10個:(以鏈接在Server上,因此配置在Provider上)

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

限制客戶端服務使用鏈接鏈接數:(若是是長鏈接,好比Dubbo協議,connections表示該服務對每一個提供者創建的長鏈接數)

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

Or:

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

若是<dubbo:service>和<dubbo:reference>都配了connections,<dubbo:reference>優先,參見:配置的覆蓋策略

延遲鏈接

(+) (#)

延遲鏈接,用於減小長鏈接數,當有調用發起時,再建立長鏈接。
只對使用長鏈接的dubbo協議生效。
< dubbo:protocol name = "dubbo" lazy = "true" />

粘滯鏈接

(+) (#)

粘滯鏈接用於有狀態服務,儘量讓客戶端老是向同一提供者發起調用,除非該提供者掛了,再連另外一臺。
粘滯鏈接將自動開啓延遲鏈接,以減小長鏈接數,參見:延遲鏈接 (+)
< dubbo:protocol name = "dubbo" sticky = "true" />

令牌驗證

(+) (#)

  • 防止消費者繞過註冊中心訪問提供者
  • 在註冊中心控制權限,以決定要不要下發令牌給消費者
  • 註冊中心可靈活改變受權方式,而不需修改或升級提供者

能夠全局設置開啓令牌驗證:

<!--隨機token令牌,使用UUID生成-->
< dubbo:provider interface = "com.foo.BarService" token = "true" />
<!--固定token令牌,至關於密碼-->
< dubbo:provider interface = "com.foo.BarService" token = "123456" />

也可在服務級別設置:

<!--隨機token令牌,使用UUID生成-->
< dubbo:service interface = "com.foo.BarService" token = "true" />
<!--固定token令牌,至關於密碼-->
< dubbo:service interface = "com.foo.BarService" token = "123456" />

還可在協議級別設置:

<!--隨機token令牌,使用UUID生成-->
< dubbo:protocol name = "dubbo" token = "true" />
<!--固定token令牌,至關於密碼-->
< dubbo:protocol name = "dubbo" token = "123456" />

路由規則

(+) (#)

2.2.0以上版本支持
路由規則擴展點:路由擴展

向註冊中心寫入路由規則:(一般由監控中心或治理中心的頁面完成)

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "condition://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode( "http://10.20.160.198/wiki/display/dubbo/host = 10.20.153.10 => host = 10.20.153.11" ) + "));

其中:

  • condition://
  • 0.0.0.0
    • 表示對全部IP地址生效,若是隻想對某個IP的生效,請填入具體IP,必填。
  • com.foo.BarService
    • 表示只對指定服務生效,必填。
  • category=routers
    • 表示該數據爲動態配置類型,必填。
  • dynamic=false
    • 表示該數據爲持久數據,當註冊方退出時,數據依然保存在註冊中心,必填。
  • enabled=true
    • 覆蓋規則是否生效,可不填,缺省生效。
  • force=false
    • 當路由結果爲空時,是否強制執行,若是不強制執行,路由結果爲空的路由規則將自動失效,可不填,缺省爲flase。
  • runtime=false
    • 是否在每次調用時執行路由規則,不然只在提供者地址列表變動時預先執行並緩存結果,調用時直接從緩存中獲取路由結果。
    • 若是用了參數路由,必須設爲true,須要注意設置會影響調用的性能,可不填,缺省爲flase。
  • priority=1
    • 路由規則的優先級,用於排序,優先級越大越靠前執行,可不填,缺省爲0。
  • rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11")
    • 表示路由規則的內容,必填。

條件路由規則

(#)

基於條件表達式的路由規則,如:

host = 10.20 . 153.10 => host = 10.20 . 153.11

規則:

  • "=>"以前的爲消費者匹配條件,全部參數和消費者的URL進行對比,當消費者知足匹配條件時,對該消費者執行後面的過濾規則。
  • "=>"以後爲提供者地址列表的過濾條件,全部參數和提供者的URL進行對比,消費者最終只拿到過濾後的地址列表。
  • 若是匹配條件爲空,表示對全部消費方應用,如:=> host != 10.20.153.11
  • 若是過濾條件爲空,表示禁止訪問,如:host = 10.20.153.10 =>

表達式:

  • 參數支持:
    • 服務調用信息,如:method, argument 等 (暫不支持參數路由)
    • URL自己的字段,如:protocol, host, port 等
    • 以及URL上的全部參數,如:application, organization 等
  • 條件支持:
    • 等號"="表示"匹配",如:host = 10.20.153.10
    • 不等號"!="表示"不匹配",如:host != 10.20.153.10
  • 值支持:
    • 以逗號","分隔多個值,如:host != 10.20.153.10,10.20.153.11
    • 以星號"*"結尾,表示通配,如:host != 10.20.*
    • 以美圓符"$"開頭,表示引用消費者參數,如:host = $host

示例:

1. 排除預發佈機:

=> host != 172.22 . 3.91

2. 白名單:(注意:一個服務只能有一條白名單規則,不然兩條規則交叉,就都被篩選掉了)

host != 10.20 . 153.10 , 10.20 . 153.11 =>

3. 黑名單:

host = 10.20 . 153.10 , 10.20 . 153.11 =>

4. 服務寄宿在應用上,只暴露一部分的機器,防止整個集羣掛掉:

=> host = 172.22 . 3.1 *, 172.22 . 3.2 *

5. 爲重要應用提供額外的機器:

application != kylin => host != 172.22 . 3.95 , 172.22 . 3.96

6. 讀寫分離:

method = find*,list*,get*,is* => host = 172.22 . 3.94 , 172.22 . 3.95 , 172.22 . 3.96
method != find*,list*,get*,is* => host = 172.22 . 3.97 , 172.22 . 3.98

7. 先後臺分離:

application = bops => host = 172.22 . 3.91 , 172.22 . 3.92 , 172.22 . 3.93
application != bops => host = 172.22 . 3.94 , 172.22 . 3.95 , 172.22 . 3.96

8. 隔離不一樣機房網段:

host != 172.22 . 3 .* => host != 172.22 . 3 .*

9. 提供者與消費者部署在同集羣內,本機只訪問本機的服務:

=> host = $host

腳本路由規則

(#)

支持JDK腳本引擎的全部腳本,好比:javascript,jruby,groovy等,經過type=javascript參數設置腳本類型,缺省爲javascript。
腳本沒有沙箱約束,可執行任意代碼,存在後門風險
"script://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode( "function route(invokers) { ... } (invokers)" )

基於腳本引擎的路由規則,如:

function route(invokers) {
     var result = new java.util.ArrayList(invokers.size());
     for (i = 0; i < invokers.size(); i ++) {
         if ( "http://10.20.160.198/wiki/display/dubbo/10.20.153.10" .equals(invokers.get(i).getUrl().getHost())) {
             result.add(invokers.get(i));
         }
     }
     return result;
} (invokers); // 表示當即執行方法

配置規則

(+) (#)

2.2.0以上版本支持

向註冊中心寫入動態配置覆蓋規則:(一般由監控中心或治理中心的頁面完成)

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&timeout=1000" ));

其中:

  • override://
    • 表示數據採用覆蓋方式,支持override和absent,可擴展,必填。
  • 0.0.0.0
    • 表示對全部IP地址生效,若是隻想覆蓋某個IP的數據,請填入具體IP,必填。
  • com.foo.BarService
    • 表示只對指定服務生效,必填。
  • category=configurators
    • 表示該數據爲動態配置類型,必填。
  • dynamic=false
    • 表示該數據爲持久數據,當註冊方退出時,數據依然保存在註冊中心,必填。
  • enabled=true
    • 覆蓋規則是否生效,可不填,缺省生效。
  • application=foo
    • 表示只對指定應用生效,可不填,表示對全部應用生效。
  • timeout=1000
    • 表示將知足以上條件的timeout參數的值覆蓋爲1000。
    • 若是想覆蓋其它參數,直接加在override的URL參數上。

示例:

1. 禁用提供者:(一般用於臨時踢除某臺提供者機器,類似的,禁止消費者訪問請使用路由規則)

override: //10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&disbaled=true

2. 調整權重:(一般用於容量評估,缺省權重爲100)

override: //10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&weight=200

3. 調整負載均衡策略:(缺省負載均衡策略爲random)

override: //10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&loadbalance=leastactive

4. 服務降級:(一般用於臨時屏蔽某個出錯的非關鍵服務)

override: //0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null

服務降級

(+) (#)

2.2.0以上版本支持
參見:配置規則

向註冊中心寫入動態配置覆蓋規則:(經過由監控中心或治理中心的頁面完成)

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null" ));

其中:

mock=force: return + null
  • 表示消費方對該服務的方法調用都直接返回null值,不發起遠程調用。
  • 屏蔽不重要服務不可用時對調用方的影響。

還能夠改成:

mock=fail: return + null
  • 表示消費方對該服務的方法調用在失敗後,再返回null值,不拋異常。
  • 容忍不重要服務不穩定時對調用方的影響。

優雅停機

(+) (#)

Dubbo是經過JDK的ShutdownHook來完成優雅停機的,因此若是用戶使用"kill -9 PID"等強制關閉指令,是不會執行優雅停機的,只有經過"kill PID"時,纔會執行。

原理:

  • 服務提供方
    • 中止時,先標記爲不接收新請求,新請求過來時直接報錯,讓客戶端重試其它機器。
    • 而後,檢測線程池中的線程是否正在運行,若是有,等待全部線程執行完成,除非超時,則強制關閉。
  • 服務消費方
    • 中止時,再也不發起新的調用請求,全部新的調用在客戶端即報錯。
    • 而後,檢測有沒有請求的響應尚未返回,等待響應返回,除非超時,則強制關閉。

設置優雅停機超時時間,缺省超時時間是10秒:(超時則強制關閉)

< dubbo:application ...>
     < dubbo:parameter key = "shutdown.timeout" value = "60000" /> <!-- 單位毫秒 -->
</ dubbo:application >

若是ShutdownHook不能生效,能夠自行調用:

ProtocolConfig.destroyAll();

主機綁定

(+) (#)

缺省主機IP查找順序:

  • 經過LocalHost.getLocalHost()獲取本機地址。
  • 若是是127.*等loopback地址,則掃描各網卡,獲取網卡IP。

註冊的地址若是獲取不正確,好比須要註冊公網地址,能夠:
1. 能夠在/etc/hosts中加入:機器名 公網IP,好比:

test1 205.182 . 23.201

2. 在dubbo.xml中加入主機地址的配置:

3. 或在dubbo.properties中加入主機地址的配置:

dubbo.protocol.host= 205.182 . 23.201

缺省主機端口與協議相關:

  • dubbo: 20880
  • rmi: 1099
  • http: 80
  • hessian: 80
  • webservice: 80
  • memcached: 11211
  • redis: 6379

主機端口配置:

1. 在dubbo.xml中加入主機地址的配置:

< dubbo:protocol name = "dubbo" port = "20880" >

3. 或在dubbo.properties中加入主機地址的配置:

dubbo.protocol.dubbo.port= 20880

日誌適配

(+) (#)

2.2.1以上版本支持
擴展點:日誌適配擴展

缺省自動查找:

  • log4j
  • slf4j
  • jcl
  • jdk

能夠經過如下方式配置日誌輸出策略:

java -Ddubbo.application.logger=log4j
dubbo.properties
dubbo.application.logger=log4j
dubbo.xml
<dubbo:application logger= "log4j" />

訪問日誌

(+) (#)

若是你想記錄每一次請求信息,可開啓訪問日誌,相似於apache的訪問日誌。
此日誌量比較大,請注意磁盤容量。

將訪問日誌輸出到當前應用的log4j日誌:

< dubbo:protocol accesslog = "true" />

將訪問日誌輸出到指定文件:

< dubbo:protocol accesslog = "http://10.20.160.198/wiki/display/dubbo/foo/bar.log" />

服務容器

(+) (#)

服務容器是一個standalone的啓動程序,由於後臺服務不須要Tomcat或JBoss等Web容器的功能,若是硬要用Web容器去加載服務提供方,增長複雜性,也浪費資源。
服務容器只是一個簡單的Main方法,並加載一個簡單的Spring容器,用於暴露服務。
服務容器的加載內容能夠擴展,內置了spring, jetty, log4j等加載,可經過Container擴展點進行擴展,參見:Container
Spring Container
  • 自動加載META-INF/spring目錄下的全部Spring配置。
  • 配置:(配在java命令-D參數或者dubbo.properties中)
    • dubbo.spring.config=classpath*:META-INF/spring/*.xml ----配置spring配置加載位置
Jetty Container
  • 啓動一個內嵌Jetty,用於彙報狀態。
  • 配置:(配在java命令-D參數或者dubbo.properties中)
    • dubbo.jetty.port=8080 ----配置jetty啓動端口
    • dubbo.jetty.directory=/foo/bar ----配置可經過jetty直接訪問的目錄,用於存放靜態文件
    • dubbo.jetty.page=log,status,system ----配置顯示的頁面,缺省加載全部頁面
Log4j Container
  • 自動配置log4j的配置,在多進程啓動時,自動給日誌文件按進程分目錄。
  • 配置:(配在java命令-D參數或者dubbo.properties中)
    • dubbo.log4j.file=/foo/bar.log ----配置日誌文件路徑
    • dubbo.log4j.level=WARN ----配置日誌級別
    • dubbo.log4j.subdirectory=20880 ----配置日誌子目錄,用於多進程啓動,避免衝突

容器啓動

如:(缺省只加載spring)

java com.alibaba.dubbo.container.Main

或:(經過main函數參數傳入要加載的容器)

java com.alibaba.dubbo.container.Main spring jetty log4j

或:(經過JVM啓動參數傳入要加載的容器)

java com.alibaba.dubbo.container.Main -Ddubbo.container=spring,jetty,log4j

或:(經過classpath下的dubbo.properties配置傳入要加載的容器)

dubbo.properties
dubbo.container=spring,jetty,log4j

Reference Config緩存

(+) (#)

ReferenceConfig實例很重,封裝了與註冊中心的鏈接以及與提供者的鏈接,須要緩存,不然重複生成ReferenceConfig可能形成性能問題而且會有內存和鏈接泄漏。API方式編程時,容易忽略此問題。

Dubbo 2.4.0+版本,提供了簡單的工具類ReferenceConfigCache用於緩存ReferenceConfig實例。

使用方式以下:

ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>();
reference.setInterface(XxxService. class );
reference.setVersion( "1.0.0" );
......
 
 
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
XxxService xxxService = cache.get(reference); // cache.get方法中會Cache Reference對象,而且調用ReferenceConfig.get方法啓動ReferenceConfig
// 注意! Cache會持有ReferenceConfig,不要在外部再調用ReferenceConfig的destroy方法,致使Cache內的ReferenceConfig失效!
 
// 使用xxxService對象
xxxService.sayHello();

消除Cache中的ReferenceConfig,銷燬ReferenceConfig並釋放對應的資源。

ReferenceConfigCache cache = ReferenceConfigCache.getCache();
cache.destroy(reference);

缺省ReferenceConfigCache把相同服務Group、接口、版本的ReferenceConfig認爲是相同,緩存一份。即以服務Group、接口、版本爲緩存的Key。

能夠修改這個策略,在ReferenceConfigCache.getCache時,傳一個KeyGenerator。詳見ReferenceConfigCache類的方法。

KeyGenerator keyGenerator = new ...
 
ReferenceConfigCache cache = ReferenceConfigCache.getCache(keyGenerator );

分佈式事務

(+) (#)

基於JTA/XA規範實現。
暫未實現。

兩階段提交:

API參考手冊

(+) (#)

Dubbo的常規功能,都保持零侵入,但有些功能不得不用API侵入才能實現。
Dubbo中除這裏聲明之外的接口或類,都是內部接口或擴展接口,普通用戶請不要直接依賴,不然升級版本可能出現不兼容。

API彙總以下:

配置API

  • com.alibaba.dubbo.config.ServiceConfig
  • com.alibaba.dubbo.config.ReferenceConfig
  • com.alibaba.dubbo.config.ProtocolConfig
  • com.alibaba.dubbo.config.RegistryConfig
  • com.alibaba.dubbo.config.MonitorConfig
  • com.alibaba.dubbo.config.ApplicationConfig
  • com.alibaba.dubbo.config.ModuleConfig
  • com.alibaba.dubbo.config.ProviderConfig
  • com.alibaba.dubbo.config.ConsumerConfig
  • com.alibaba.dubbo.config.MethodConfig
  • com.alibaba.dubbo.config.ArgumentConfig

註解API

  • com.alibaba.dubbo.config.annotation.Service
  • com.alibaba.dubbo.config.annotation.Reference

模型API

  • com.alibaba.dubbo.common.URL
  • com.alibaba.dubbo.rpc.RpcException

上下文API

服務API

  • com.alibaba.dubbo.rpc.service.GenericService
  • com.alibaba.dubbo.rpc.service.GenericException
  • com.alibaba.dubbo.rpc.service.EchoService

配置參考手冊

(+) (#)

這裏以Xml配置爲準,列舉全部配置項,其它配置方式,請參見相應轉換關係:屬性配置註解配置API配置

注意:只有group,interface,version是服務的匹配條件,三者決定是否是同一個服務,其它配置項均爲調優和治理參數。

全部配置項分爲三大類,參見下表中的"做用"一列。

  • 服務發現:表示該配置項用於服務的註冊與發現,目的是讓消費方找到提供方。
  • 服務治理:表示該配置項用於治理服務間的關係,或爲開發測試提供便利條件。
  • 性能調優:表示該配置項用於調優性能,不一樣的選項對性能會產生影響。

全部配置最終都將轉換爲URL表示,並由服務提供方生成,經註冊中心傳遞給消費方,各屬性對應URL的參數,參見配置項一覽表中的"對應URL參數"列。
URL格式:

protocol://username:password@host:port/path?key=value&key=value

Schema: http://code.alibabatech.com/schema/dubbo/dubbo.xsd

<dubbo:service/>

(+) (#)

服務提供者暴露服務配置:
配置類:com.alibaba.dubbo.config.ServiceConfig

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:service> interface   class 必填   服務發現 服務接口名 1.0.0以上版本
<dubbo:service> ref   object 必填   服務發現 服務對象實現引用 1.0.0以上版本
<dubbo:service> version version string 可選 0.0.0 服務發現 服務版本,建議使用兩位數字版本,如:1.0,一般在接口不兼容時版本號才須要升級 1.0.0以上版本
<dubbo:service> group group string 可選   服務發現 服務分組,當一個接口有多個實現,能夠用分組區分 1.0.7以上版本
<dubbo:service> path <path> string 可選 缺省爲接口名 服務發現 服務路徑 (注意:1.0不支持自定義路徑,老是使用接口名,若是有1.0調2.0,配置服務路徑可能不兼容) 1.0.12以上版本
<dubbo:service> delay delay int 可選 0 性能調優 延遲註冊服務時間(毫秒) ,設爲-1時,表示延遲到Spring容器初始化完成時暴露服務 1.0.14以上版本
<dubbo:service> timeout timeout int 可選 1000 性能調優 遠程服務調用超時時間(毫秒) 2.0.0以上版本
<dubbo:service> retries retries int 可選 2 性能調優 遠程服務調用重試次數,不包括第一次調用,不須要重試請設爲0 2.0.0以上版本
<dubbo:service> connections connections int 可選 100 性能調優 對每一個提供者的最大鏈接數,rmi、http、hessian等短鏈接協議表示限制鏈接數,dubbo等長鏈接協表示創建的長鏈接個數 2.0.0以上版本
<dubbo:service> loadbalance loadbalance string 可選 random 性能調優 負載均衡策略,可選值:random,roundrobin,leastactive,分別表示:隨機,輪循,最少活躍調用 2.0.0以上版本
<dubbo:service> async async boolean 可選 false 性能調優 是否缺省異步執行,不可靠異步,只是忽略返回值,不阻塞執行線程 2.0.0以上版本
<dubbo:service> stub stub class/boolean 可選 false 服務治理 設爲true,表示使用缺省代理類名,即:接口名 + Local後綴,服務接口客戶端本地代理類名,用於在客戶端執行本地邏輯,如本地緩存等,該本地代理類的構造函數必須容許傳入遠程代理對象,構造函數如:public XxxServiceLocal(XxxService xxxService) 2.0.0以上版本
<dubbo:service> mock mock class/boolean 可選 false 服務治理 設爲true,表示使用缺省Mock類名,即:接口名 + Mock後綴,服務接口調用失敗Mock實現類,該Mock類必須有一個無參構造函數,與Local的區別在於,Local老是被執行,而Mock只在出現非業務異常(好比超時,網絡異常等)時執行,Local在遠程調用以前執行,Mock在遠程調用後執行。 2.0.0以上版本
<dubbo:service> token token string/boolean 可選 false 服務治理 令牌驗證,爲空表示不開啓,若是爲true,表示隨機生成動態令牌,不然使用靜態令牌,令牌的做用是防止消費者繞過註冊中心直接訪問,保證註冊中心的受權功能有效,若是使用點對點調用,需關閉令牌功能 2.0.0以上版本
<dubbo:service> registry   string 可選 缺省向全部registry註冊 配置關聯 向指定註冊中心註冊,在多個註冊中心時使用,值爲<dubbo:registry>的id屬性,多個註冊中心ID用逗號分隔,若是不想將該服務註冊到任何registry,可將值設爲N/A 2.0.0以上版本
<dubbo:service> provider   string 可選 缺使用第一個provider配置 配置關聯 指定provider,值爲<dubbo:provider>的id屬性 2.0.0以上版本
<dubbo:service> deprecated deprecated boolean 可選 false 服務治理 服務是否過期,若是設爲true,消費方引用時將打印服務過期警告error日誌 2.0.5以上版本
<dubbo:service> dynamic dynamic boolean 可選 true 服務治理 服務是否動態註冊,若是設爲false,註冊後將顯示後disable狀態,需人工啓用,而且服務提供者中止時,也不會自動取消冊,需人工禁用。 2.0.5以上版本
<dubbo:service> accesslog accesslog string/boolean 可選 false 服務治理 設爲true,將向logger中輸出訪問日誌,也可填寫訪問日誌文件路徑,直接把訪問日誌輸出到指定文件 2.0.5以上版本
<dubbo:service> owner owner string 可選   服務治理 服務負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.0.5以上版本
<dubbo:service> document document string 可選   服務治理 服務文檔URL 2.0.5以上版本
<dubbo:service> weight weight int 可選   性能調優 服務權重 2.0.5以上版本
<dubbo:service> executes executes int 可選 0 性能調優 服務提供者每服務每方法最大可並行執行請求數 2.0.5以上版本
<dubbo:service> actives actives int 可選 0 性能調優 每服務消費者每服務每方法最大併發調用數 2.0.5以上版本
<dubbo:service> proxy proxy string 可選 javassist 性能調優 生成動態代理方式,可選:jdk/javassist 2.0.5以上版本
<dubbo:service> cluster cluster string 可選 failover 性能調優 集羣方式,可選:failover/failfast/failsafe/failback/forking 2.0.5以上版本
<dubbo:service> filter service.filter string 可選 default 性能調優 服務提供方遠程調用過程攔截器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:service> listener exporter.listener string 可選 default 性能調優 服務提供方導出服務監聽器名稱,多個名稱用逗號分隔  
<dubbo:service> protocol   string 可選   配置關聯 使用指定的協議暴露服務,在多協議時使用,值爲<dubbo:protocol>的id屬性,多個協議ID用逗號分隔 2.0.5以上版本
<dubbo:service> layer layer string 可選   服務治理 服務提供者所在的分層。如:biz、dao、intl:web、china:acton。 2.0.7以上版本
<dubbo:service> register register boolean 可選 true 服務治理 該協議的服務是否註冊到註冊中心 2.0.8以上版本

<dubbo:reference/>

(+) (#)

服務消費者引用服務配置:
配置類:com.alibaba.dubbo.config.ReferenceConfig

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:reference> id   string 必填   配置關聯 服務引用BeanId 1.0.0以上版本
<dubbo:reference> interface   class 必填   服務發現 服務接口名 1.0.0以上版本
<dubbo:reference> version version string 可選   服務發現 服務版本,與服務提供者的版本一致 1.0.0以上版本
<dubbo:reference> group group string 可選   服務發現 服務分組,當一個接口有多個實現,能夠用分組區分,必需和服務提供方一致 1.0.7以上版本
<dubbo:reference> timeout timeout long 可選 缺省使用<dubbo:consumer>的timeout 性能調優 服務方法調用超時時間(毫秒) 1.0.5以上版本
<dubbo:reference> retries retries int 可選 缺省使用<dubbo:consumer>的retries 性能調優 遠程服務調用重試次數,不包括第一次調用,不須要重試請設爲0 2.0.0以上版本
<dubbo:reference> connections connections int 可選 缺省使用<dubbo:consumer>的connections 性能調優 對每一個提供者的最大鏈接數,rmi、http、hessian等短鏈接協議表示限制鏈接數,dubbo等長鏈接協表示創建的長鏈接個數 2.0.0以上版本
<dubbo:reference> loadbalance loadbalance string 可選 缺省使用<dubbo:consumer>的loadbalance 性能調優 負載均衡策略,可選值:random,roundrobin,leastactive,分別表示:隨機,輪循,最少活躍調用 2.0.0以上版本
<dubbo:reference> async async boolean 可選 缺省使用<dubbo:consumer>的async 性能調優 是否異步執行,不可靠異步,只是忽略返回值,不阻塞執行線程 2.0.0以上版本
<dubbo:reference> generic generic boolean 可選 缺省使用<dubbo:consumer>的generic 服務治理 是否缺省泛化接口,若是爲泛化接口,將返回GenericService 2.0.0以上版本
<dubbo:reference> check check boolean 可選 缺省使用<dubbo:consumer>的check 服務治理 啓動時檢查提供者是否存在,true報錯,false忽略 2.0.0以上版本
<dubbo:reference> url <url> string 可選   服務治理 點對點直連服務提供者地址,將繞過註冊中心 1.0.6以上版本
<dubbo:reference> stub stub class/boolean 可選   服務治理 服務接口客戶端本地代理類名,用於在客戶端執行本地邏輯,如本地緩存等,該本地代理類的構造函數必須容許傳入遠程代理對象,構造函數如:public XxxServiceLocal(XxxService xxxService) 2.0.0以上版本
<dubbo:reference> mock mock class/boolean 可選   服務治理 服務接口調用失敗Mock實現類名,該Mock類必須有一個無參構造函數,與Local的區別在於,Local老是被執行,而Mock只在出現非業務異常(好比超時,網絡異常等)時執行,Local在遠程調用以前執行,Mock在遠程調用後執行。 Dubbo1.0.13及其以上版本支持
<dubbo:reference> cache cache string/boolean 可選   服務治理 以調用參數爲key,緩存返回結果,可選:lru, threadlocal, jcache等 Dubbo2.1.0及其以上版本支持
<dubbo:reference> validation validation boolean 可選   服務治理 是否啓用JSR303標準註解驗證,若是啓用,將對方法參數上的註解進行校驗 Dubbo2.1.0及其以上版本支持
<dubbo:reference> proxy proxy boolean 可選 javassist 性能調優 選擇動態代理實現策略,可選:javassist, jdk 2.0.2以上版本
<dubbo:reference> client client string 可選   性能調優 客戶端傳輸類型設置,如Dubbo協議的netty或mina。 Dubbo2.0.0以上版本支持
<dubbo:reference> registry   string 可選 缺省將從全部註冊中心獲服務列表後合併結果 配置關聯 從指定註冊中心註冊獲取服務列表,在多個註冊中心時使用,值爲<dubbo:registry>的id屬性,多個註冊中心ID用逗號分隔 2.0.0以上版本
<dubbo:reference> owner owner string 可選   服務治理 調用服務負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.0.5以上版本
<dubbo:reference> actives actives int 可選 0 性能調優 每服務消費者每服務每方法最大併發調用數 2.0.5以上版本
<dubbo:reference> cluster cluster string 可選 failover 性能調優 集羣方式,可選:failover/failfast/failsafe/failback/forking 2.0.5以上版本
<dubbo:reference> filter reference.filter string 可選 default 性能調優 服務消費方遠程調用過程攔截器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:reference> listener invoker.listener string 可選 default 性能調優 服務消費方引用服務監聽器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:reference> layer layer string 可選   服務治理 服務調用者所在的分層。如:biz、dao、intl:web、china:acton。 2.0.7以上版本
<dubbo:reference> init init boolean 可選 false 性能調優 是否在afterPropertiesSet()時飢餓初始化引用,不然等到有人注入或引用該實例時再初始化。 2.0.10以上版本
<dubbo:reference> protocol protocol string 可選   服力治理 只調用指定協議的服務提供方,其它協議忽略。 2.2.0以上版本

<dubbo:protocol/>

(+) (#)

服務提供者協議配置:
配置類:com.alibaba.dubbo.config.ProtocolConfig
說明:若是須要支持多協議,能夠聲明多個<dubbo:protocol>標籤,並在<dubbo:service>中經過protocol屬性指定使用的協議。

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:protocol> id   string 可選 dubbo 配置關聯 協議BeanId,能夠在<dubbo:service protocol="">中引用此ID,若是ID不填,缺省和name屬性值同樣,重複則在name後加序號。 2.0.5以上版本
<dubbo:protocol> name <protocol> string 必填 dubbo 性能調優 協議名稱 2.0.5以上版本
<dubbo:protocol> port <port> int 可選 dubbo協議缺省端口爲20880,rmi協議缺省端口爲1099,http和hessian協議缺省端口爲80 
若是配置爲-1 或者 沒有配置port,則會分配一個沒有被佔用的端口。Dubbo 2.4.0+,分配的端口在協議缺省端口的基礎上增加,確保端口段可控。
服務發現 服務端口 2.0.5以上版本
<dubbo:protocol> host <host> string 可選 自動查找本機IP 服務發現 -服務主機名,多網卡選擇或指定VIP及域名時使用,爲空則自動查找本機IP,-建議不要配置,讓Dubbo自動獲取本機IP 2.0.5以上版本
<dubbo:protocol> threadpool threadpool string 可選 fixed 性能調優 線程池類型,可選:fixed/cached 2.0.5以上版本
<dubbo:protocol> threads threads int 可選 100 性能調優 服務線程池大小(固定大小) 2.0.5以上版本
<dubbo:protocol> iothreads threads int 可選 cpu個數+1 性能調優 io線程池大小(固定大小) 2.0.5以上版本
<dubbo:protocol> accepts accepts int 可選 0 性能調優 服務提供方最大可接受鏈接數 2.0.5以上版本
<dubbo:protocol> payload payload int 可選 88388608(=8M) 性能調優 請求及響應數據包大小限制,單位:字節 2.0.5以上版本
<dubbo:protocol> codec codec string 可選 dubbo 性能調優 協議編碼方式 2.0.5以上版本
<dubbo:protocol> serialization serialization string 可選 dubbo協議缺省爲hessian2,rmi協議缺省爲java,http協議缺省爲json 性能調優 協議序列化方式,當協議支持多種序列化方式時使用,好比:dubbo協議的dubbo,hessian2,java,compactedjava,以及http協議的json等 2.0.5以上版本
<dubbo:protocol> accesslog accesslog string/boolean 可選   服務治理 設爲true,將向logger中輸出訪問日誌,也可填寫訪問日誌文件路徑,直接把訪問日誌輸出到指定文件 2.0.5以上版本
<dubbo:protocol> path <path> string 可選   服務發現 提供者上下文路徑,爲服務path的前綴 2.0.5以上版本
<dubbo:protocol> transporter transporter string 可選 dubbo協議缺省爲netty 性能調優 協議的服務端和客戶端實現類型,好比:dubbo協議的mina,netty等,能夠分拆爲server和client配置 2.0.5以上版本
<dubbo:protocol> server server string 可選 dubbo協議缺省爲netty,http協議缺省爲servlet 性能調優 協議的服務器端實現類型,好比:dubbo協議的mina,netty等,http協議的jetty,servlet等 2.0.5以上版本
<dubbo:protocol> client client string 可選 dubbo協議缺省爲netty 性能調優 協議的客戶端實現類型,好比:dubbo協議的mina,netty等 2.0.5以上版本
<dubbo:protocol> dispatcher dispatcher string 可選 dubbo協議缺省爲all 性能調優 協議的消息派發方式,用於指定線程模型,好比:dubbo協議的all, direct, message, execution, connection等 2.1.0以上版本
<dubbo:protocol> queues queues int 可選 0 性能調優 線程池隊列大小,當線程池滿時,排隊等待執行的隊列大小,建議不要設置,當線程程池時應當即失敗,重試其它服務提供機器,而不是排隊,除非有特殊需求。 2.0.5以上版本
<dubbo:protocol> charset charset string 可選 UTF-8 性能調優 序列化編碼 2.0.5以上版本
<dubbo:protocol> buffer buffer int 可選 8192 性能調優 網絡讀寫緩衝區大小 2.0.5以上版本
<dubbo:protocol> heartbeat heartbeat int 可選 0 性能調優 心跳間隔,對於長鏈接,當物理層斷開時,好比拔網線,TCP的FIN消息來不及發送,對方收不到斷開事件,此時須要心跳來幫助檢查鏈接是否已斷開 2.0.10以上版本
<dubbo:protocol> telnet telnet string 可選   服務治理 所支持的telnet命令,多個命令用逗號分隔 2.0.5以上版本
<dubbo:protocol> register register boolean 可選 true 服務治理 該協議的服務是否註冊到註冊中心 2.0.8以上版本
<dubbo:protocol> contextpath contextpath String 可選 缺省爲空串 服務治理   2.0.6以上版本

<dubbo:registry/>

(+) (#)

註冊中心配置:
配置類:com.alibaba.dubbo.config.RegistryConfig
說明:若是有多個不一樣的註冊中心,能夠聲明多個<dubbo:registry>標籤,並在<dubbo:service>或<dubbo:reference>的registry屬性指定使用的註冊中心。

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:registry> id   string 可選   配置關聯 註冊中心引用BeanId,能夠在<dubbo:service registry="">或<dubbo:reference registry="">中引用此ID 1.0.16以上版本
<dubbo:registry> address <host:port> string 必填   服務發現 註冊中心服務器地址,若是地址沒有端口缺省爲9090,同一集羣內的多個地址用逗號分隔,如:ip:port,ip:port,不一樣集羣的註冊中心,請配置多個<dubbo:registry>標籤 1.0.16以上版本
<dubbo:registry> protocol <protocol> string 可選 dubbo 服務發現 注同中心地址協議,支持dubbo, http, local三種協議,分別表示,dubbo地址,http地址,本地註冊中心 2.0.0以上版本
<dubbo:registry> port <port> int 可選 9090 服務發現 註冊中心缺省端口,當address沒有帶端口時使用此端口作爲缺省值 2.0.0以上版本
<dubbo:registry> username <username> string 可選   服務治理 登陸註冊中心用戶名,若是註冊中心不須要驗證可不填 2.0.0以上版本
<dubbo:registry> password <password> string 可選   服務治理 登陸註冊中心密碼,若是註冊中心不須要驗證可不填 2.0.0以上版本
<dubbo:registry> transport registry.transporter string 可選 netty 性能調優 網絡傳輸方式,可選mina,netty 2.0.0以上版本
<dubbo:registry> timeout registry.timeout int 可選 5000 性能調優 註冊中心請求超時時間(毫秒) 2.0.0以上版本
<dubbo:registry> session registry.session int 可選 60000 性能調優 註冊中心會話超時時間(毫秒),用於檢測提供者非正常斷線後的髒數據,好比用心跳檢測的實現,此時間就是心跳間隔,不一樣註冊中心實現不同。 2.1.0以上版本
<dubbo:registry> file registry.file string 可選   服務治理 使用文件緩存註冊中心地址列表及服務提供者列表,應用重啓時將基於此文件恢復,注意:兩個註冊中心不能使用同一文件存儲 2.0.0以上版本
<dubbo:registry> wait registry.wait int 可選 0 性能調優 中止時等待通知完成時間(毫秒) 2.0.0以上版本
<dubbo:registry> check check boolean 可選 true 服務治理 註冊中心不存在時,是否報錯 2.0.0以上版本
<dubbo:registry> register register boolean 可選 true 服務治理 是否向此註冊中心註冊服務,若是設爲false,將只訂閱,不註冊 2.0.5以上版本
<dubbo:registry> subscribe subscribe boolean 可選 true 服務治理 是否向此註冊中心訂閱服務,若是設爲false,將只註冊,不訂閱 2.0.5以上版本
<dubbo:registry> dynamic dynamic boolean 可選 true 服務治理 服務是否動態註冊,若是設爲false,註冊後將顯示後disable狀態,需人工啓用,而且服務提供者中止時,也不會自動取消冊,需人工禁用。 2.0.5以上版本

<dubbo:monitor/>

(+) (#)

監控中心配置:
配置類:com.alibaba.dubbo.config.MonitorConfig

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:monitor> protocol protocol string 可選 dubbo 服務治理 監控中心協議,若是爲protocol="registry",表示從註冊中心發現監控中心地址,不然直連監控中心。 2.0.9以上版本
<dubbo:monitor> address <url> string 可選 N/A 服務治理 直連監控中心服務器地址,address="10.20.130.230:12080" 1.0.16以上版本

<dubbo:application/>

(+) (#)

應用信息配置:
配置類:com.alibaba.dubbo.config.ApplicationConfig

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:application> name application string 必填   服務治理 當前應用名稱,用於註冊中心計算應用間依賴關係,注意:消費者和提供者應用名不要同樣,此參數不是匹配條件,你當前項目叫什麼名字就填什麼,和提供者消費者角色無關,好比:kylin應用調用了morgan應用的服務,則kylin項目配成kylin,morgan項目配成morgan,可能kylin也提供其它服務給別人使用,但kylin項目永遠配成kylin,這樣註冊中心將顯示kylin依賴於morgan 1.0.16以上版本
<dubbo:application> version application.version string 可選   服務治理 當前應用的版本 2.2.0以上版本
<dubbo:application> owner owner string 可選   服務治理 應用負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.0.5以上版本
<dubbo:application> organization organization string 可選   服務治理 組織名稱(BU或部門),用於註冊中心區分服務來源,此配置項建議不要使用autoconfig,直接寫死在配置中,好比china,intl,itu,crm,asc,dw,aliexpress等 2.0.0以上版本
<dubbo:application> architecture architecture  string 可選   服務治理 用於服務分層對應的架構。如,intl、china。不一樣的架構使用不一樣的分層。 2.0.7以上版本
<dubbo:application> environment environment string 可選   服務治理 應用環境,如:develop/test/product,不一樣環境使用不一樣的缺省值,以及做爲只用於開發測試功能的限制條件 2.0.0以上版本
<dubbo:application> compiler compiler string 可選 javassist 性能優化 Java字節碼編譯器,用於動態類的生成,可選:jdk或javassist 2.1.0以上版本
<dubbo:application> logger logger string 可選 slf4j 性能優化 日誌輸出方式,可選:slf4j,jcl,log4j,jdk 2.2.0以上版本

<dubbo:module/>

(+) (#)

模塊信息配置:
配置類:com.alibaba.dubbo.config.ModuleConfig

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:module> name module string 必填   服務治理 當前模塊名稱,用於註冊中心計算模塊間依賴關係 2.2.0以上版本
<dubbo:module> version module.version string 可選   服務治理 當前模塊的版本 2.2.0以上版本
<dubbo:module> owner owner string 可選   服務治理 模塊負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.2.0以上版本
<dubbo:module> organization organization string 可選   服務治理 組織名稱(BU或部門),用於註冊中心區分服務來源,此配置項建議不要使用autoconfig,直接寫死在配置中,好比china,intl,itu,crm,asc,dw,aliexpress等 2.2.0以上版本

<dubbo:provider/>

(+) (#)

服務提供者缺省值配置:
配置類:com.alibaba.dubbo.config.ProviderConfig
說明:該標籤爲<dubbo:service>和<dubbo:protocol>標籤的缺省值設置。

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:provider> id   string 可選 dubbo 配置關聯 協議BeanId,能夠在<dubbo:service proivder="">中引用此ID 1.0.16以上版本
<dubbo:provider> protocol <protocol> string 可選 dubbo 性能調優 協議名稱 1.0.16以上版本
<dubbo:provider> host <host> string 可選 自動查找本機IP 服務發現 服務主機名,多網卡選擇或指定VIP及域名時使用,爲空則自動查找本機IP,建議不要配置,讓Dubbo自動獲取本機IP 1.0.16以上版本
<dubbo:provider> threads threads int 可選 100 性能調優 服務線程池大小(固定大小) 1.0.16以上版本
<dubbo:provider> payload payload int 可選 88388608(=8M) 性能調優 請求及響應數據包大小限制,單位:字節 2.0.0以上版本
<dubbo:provider> path <path> string 可選   服務發現 提供者上下文路徑,爲服務path的前綴 2.0.0以上版本
<dubbo:provider> server server string 可選 dubbo協議缺省爲netty,http協議缺省爲servlet 性能調優 協議的服務器端實現類型,好比:dubbo協議的mina,netty等,http協議的jetty,servlet等 2.0.0以上版本
<dubbo:provider> client client string 可選 dubbo協議缺省爲netty 性能調優 協議的客戶端實現類型,好比:dubbo協議的mina,netty等 2.0.0以上版本
<dubbo:provider> codec codec string 可選 dubbo 性能調優 協議編碼方式 2.0.0以上版本
<dubbo:provider> serialization serialization string 可選 dubbo協議缺省爲hessian2,rmi協議缺省爲java,http協議缺省爲json 性能調優 協議序列化方式,當協議支持多種序列化方式時使用,好比:dubbo協議的dubbo,hessian2,java,compactedjava,以及http協議的json,xml等 2.0.5以上版本
<dubbo:provider> default   boolean 可選 false 配置關聯 是否爲缺省協議,用於多協議 1.0.16以上版本
<dubbo:provider> filter service.filter string 可選   性能調優 服務提供方遠程調用過程攔截器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:provider> listener exporter.listener string 可選   性能調優 服務提供方導出服務監聽器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:provider> threadpool threadpool string 可選 fixed 性能調優 線程池類型,可選:fixed/cached 2.0.5以上版本
<dubbo:provider> accepts accepts int 可選 0 性能調優 服務提供者最大可接受鏈接數 2.0.5以上版本
<dubbo:provider> version version string 可選 0.0.0 服務發現 服務版本,建議使用兩位數字版本,如:1.0,一般在接口不兼容時版本號才須要升級 2.0.5以上版本
<dubbo:provider> group group string 可選   服務發現 服務分組,當一個接口有多個實現,能夠用分組區分 2.0.5以上版本
<dubbo:provider> delay delay int 可選 0 性能調優 延遲註冊服務時間(毫秒)- ,設爲-1時,表示延遲到Spring容器初始化完成時暴露服務 2.0.5以上版本
<dubbo:provider> timeout default.timeout int 可選 1000 性能調優 遠程服務調用超時時間(毫秒) 2.0.5以上版本
<dubbo:provider> retries default.retries int 可選 2 性能調優 遠程服務調用重試次數,不包括第一次調用,不須要重試請設爲0 2.0.5以上版本
<dubbo:provider> connections default.connections int 可選 0 性能調優 對每一個提供者的最大鏈接數,rmi、http、hessian等短鏈接協議表示限制鏈接數,dubbo等長鏈接協表示創建的長鏈接個數 2.0.5以上版本
<dubbo:provider> loadbalance default.loadbalance string 可選 random 性能調優 負載均衡策略,可選值:random,roundrobin,leastactive,分別表示:隨機,輪循,最少活躍調用 2.0.5以上版本
<dubbo:provider> async default.async boolean 可選 false 性能調優 是否缺省異步執行,不可靠異步,只是忽略返回值,不阻塞執行線程 2.0.5以上版本
<dubbo:provider> stub stub boolean 可選 false 服務治理 設爲true,表示使用缺省代理類名,即:接口名 + Local後綴。 2.0.5以上版本
<dubbo:provider> mock mock boolean 可選 false 服務治理 設爲true,表示使用缺省Mock類名,即:接口名 + Mock後綴。 2.0.5以上版本
<dubbo:provider> token token boolean 可選 false 服務治理 令牌驗證,爲空表示不開啓,若是爲true,表示隨機生成動態令牌 2.0.5以上版本
<dubbo:provider> registry registry string 可選 缺省向全部registry註冊 配置關聯 向指定註冊中心註冊,在多個註冊中心時使用,值爲<dubbo:registry>的id屬性,多個註冊中心ID用逗號分隔,若是不想將該服務註冊到任何registry,可將值設爲N/A 2.0.5以上版本
<dubbo:provider> dynamic dynamic boolean 可選 true 服務治理 服務是否動態註冊,若是設爲false,註冊後將顯示後disable狀態,需人工啓用,而且服務提供者中止時,也不會自動取消冊,需人工禁用。 2.0.5以上版本
<dubbo:provider> accesslog accesslog string/boolean 可選 false 服務治理 設爲true,將向logger中輸出訪問日誌,也可填寫訪問日誌文件路徑,直接把訪問日誌輸出到指定文件 2.0.5以上版本
<dubbo:provider> owner owner string 可選   服務治理 服務負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.0.5以上版本
<dubbo:provider> document document string 可選   服務治理 服務文檔URL 2.0.5以上版本
<dubbo:provider> weight weight int 可選   性能調優 服務權重 2.0.5以上版本
<dubbo:provider> executes executes int 可選 0 性能調優 服務提供者每服務每方法最大可並行執行請求數 2.0.5以上版本
<dubbo:provider> actives default.actives int 可選 0 性能調優 每服務消費者每服務每方法最大併發調用數 2.0.5以上版本
<dubbo:provider> proxy proxy string 可選 javassist 性能調優 生成動態代理方式,可選:jdk/javassist 2.0.5以上版本
<dubbo:provider> cluster default.cluster string 可選 failover 性能調優 集羣方式,可選:failover/failfast/failsafe/failback/forking 2.0.5以上版本
<dubbo:provider> deprecated deprecated boolean 可選 false 服務治理 服務是否過期,若是設爲true,消費方引用時將打印服務過期警告error日誌 2.0.5以上版本
<dubbo:provider> queues queues int 可選 0 性能調優 線程池隊列大小,當線程池滿時,排隊等待執行的隊列大小,建議不要設置,當線程程池時應當即失敗,重試其它服務提供機器,而不是排隊,除非有特殊需求。 2.0.5以上版本
<dubbo:provider> charset charset string 可選 UTF-8 性能調優 序列化編碼 2.0.5以上版本
<dubbo:provider> buffer buffer int 可選 8192 性能調優 網絡讀寫緩衝區大小 2.0.5以上版本
<dubbo:provider> iothreads iothreads int 可選 CPU + 1 性能調優 IO線程池,接收網絡讀寫中斷,以及序列化和反序列化,不處理業務,業務線程池參見threads配置,此線程池和CPU相關,不建議配置。 2.0.5以上版本
<dubbo:provider> telnet telnet string 可選   服務治理 所支持的telnet命令,多個命令用逗號分隔 2.0.5以上版本
<dubbo:service> contextpath contextpath String 可選 缺省爲空串 服務治理   2.0.6以上版本
<dubbo:provider> layer layer string 可選   服務治理 服務提供者所在的分層。如:biz、dao、intl:web、china:acton。 2.0.7以上版本

<dubbo:consumer/>

(+) (#)

服務消費者缺省值配置:
配置類:com.alibaba.dubbo.config.ConsumerConfig
說明:該標籤爲<dubbo:reference>標籤的缺省值設置。

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:consumer> timeout default.timeout int 可選 1000 性能調優 遠程服務調用超時時間(毫秒) 1.0.16以上版本
<dubbo:consumer> retries default.retries int 可選 2 性能調優 遠程服務調用重試次數,不包括第一次調用,不須要重試請設爲0 1.0.16以上版本
<dubbo:consumer> loadbalance default.loadbalance string 可選 random 性能調優 負載均衡策略,可選值:random,roundrobin,leastactive,分別表示:隨機,輪循,最少活躍調用 1.0.16以上版本
<dubbo:consumer> async default.async boolean 可選 false 性能調優 是否缺省異步執行,不可靠異步,只是忽略返回值,不阻塞執行線程 2.0.0以上版本
<dubbo:consumer> connections default.connections int 可選 100 性能調優 每一個服務對每一個提供者的最大鏈接數,rmi、http、hessian等短鏈接協議支持此配置,dubbo協議長鏈接不支持此配置 1.0.16以上版本
<dubbo:consumer> generic generic boolean 可選 false 服務治理 是否缺省泛化接口,若是爲泛化接口,將返回GenericService 2.0.0以上版本
<dubbo:consumer> check check boolean 可選 true 服務治理 啓動時檢查提供者是否存在,true報錯,false忽略 1.0.16以上版本
<dubbo:consumer> proxy proxy string 可選 javassist 性能調優 生成動態代理方式,可選:jdk/javassist 2.0.5以上版本
<dubbo:consumer> owner owner string 可選   服務治理 調用服務負責人,用於服務治理,請填寫負責人公司郵箱前綴 2.0.5以上版本
<dubbo:consumer> actives default.actives int 可選 0 性能調優 每服務消費者每服務每方法最大併發調用數 2.0.5以上版本
<dubbo:consumer> cluster default.cluster string 可選 failover 性能調優 集羣方式,可選:failover/failfast/failsafe/failback/forking 2.0.5以上版本
<dubbo:consumer> filter reference.filter string 可選   性能調優 服務消費方遠程調用過程攔截器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:consumer> listener invoker.listener string 可選   性能調優 服務消費方引用服務監聽器名稱,多個名稱用逗號分隔 2.0.5以上版本
<dubbo:consumer> registry   string 可選 缺省向全部registry註冊 配置關聯 向指定註冊中心註冊,在多個註冊中心時使用,值爲<dubbo:registry>的id屬性,多個註冊中心ID用逗號分隔,若是不想將該服務註冊到任何registry,可將值設爲N/A 2.0.5以上版本
<dubbo:consumer> layer layer string 可選   服務治理 服務調用者所在的分層。如:biz、dao、intl:web、china:acton。 2.0.7以上版本
<dubbo:consumer> init init boolean 可選 false 性能調優 是否在afterPropertiesSet()時飢餓初始化引用,不然等到有人注入或引用該實例時再初始化。 2.0.10以上版本
<dubbo:consumer> cache cache string/boolean 可選   服務治理 以調用參數爲key,緩存返回結果,可選:lru, threadlocal, jcache等 Dubbo2.1.0及其以上版本支持
<dubbo:consumer> validation validation boolean 可選   服務治理 是否啓用JSR303標準註解驗證,若是啓用,將對方法參數上的註解進行校驗 Dubbo2.1.0及其以上版本支持

<dubbo:method/>

(+) (#)

方法級配置:
配置類:com.alibaba.dubbo.config.MethodConfig
說明:該標籤爲<dubbo:service>或<dubbo:reference>的子標籤,用於控制到方法級,

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:method> name   string 必填   標識 方法名 1.0.8以上版本
<dubbo:method> timeout <metodName>.timeout int 可選 缺省爲的timeout 性能調優 方法調用超時時間(毫秒) 1.0.8以上版本
<dubbo:method> retries <metodName>.retries int 可選 缺省爲<dubbo:reference>的retries 性能調優 遠程服務調用重試次數,不包括第一次調用,不須要重試請設爲0 2.0.0以上版本
<dubbo:method> loadbalance <metodName>.loadbalance string 可選 缺省爲的loadbalance 性能調優 負載均衡策略,可選值:random,roundrobin,leastactive,分別表示:隨機,輪循,最少活躍調用 2.0.0以上版本
<dubbo:method> async <metodName>.async boolean 可選 缺省爲<dubbo:reference>的async 性能調優 是否異步執行,不可靠異步,只是忽略返回值,不阻塞執行線程 1.0.9以上版本
<dubbo:method> sent <methodName>.sent boolean 可選 true 性能調優 異步調用時,標記sent=true時,表示網絡已發出數據 2.0.6以上版本
<dubbo:method> actives <metodName>.actives int 可選 0 性能調優 每服務消費者最大併發調用限制 2.0.5以上版本
<dubbo:method> executes <metodName>.executes int 可選 0 性能調優 每服務每方法最大使用線程數限制- -,此屬性只在<dubbo:method>做爲<dubbo:service>子標籤時有效 2.0.5以上版本
<dubbo:method> deprecated <methodName>.deprecated boolean 可選 false 服務治理 服務方法是否過期,此屬性只在<dubbo:method>做爲<dubbo:service>子標籤時有效 2.0.5以上版本
<dubbo:method> sticky <methodName>.sticky boolean 可選 false 服務治理 設置true 該接口上的全部方法使用同一個provider.若是須要更復雜的規則,請使用用路由 2.0.6以上版本
<dubbo:method> return <methodName>.return boolean 可選 true 性能調優 方法調用是否須要返回值,async設置爲true時才生效,若是設置爲true,則返回future,或回調onreturn等方法,若是設置爲false,則請求發送成功後直接返回Null 2.0.6以上版本
<dubbo:method> oninvoke attribute屬性,不在URL中體現 String 可選   性能調優 方法執行前攔截 2.0.6以上版本
<dubbo:method> onreturn attribute屬性,不在URL中體現 String 可選   性能調優 方法執行返回後攔截 2.0.6以上版本
<dubbo:method> onthrow attribute屬性,不在URL中體現 String 可選   性能調優 方法執行有異常攔截 2.0.6以上版本
<dubbo:method> cache <methodName>.cache string/boolean 可選   服務治理 以調用參數爲key,緩存返回結果,可選:lru, threadlocal, jcache等 Dubbo2.1.0及其以上版本支持
<dubbo:method> validation <methodName>.validation boolean 可選   服務治理 是否啓用JSR303標準註解驗證,若是啓用,將對方法參數上的註解進行校驗 Dubbo2.1.0及其以上版本支持

好比:

< dubbo:reference interface = "com.xxx.XxxService" >
     < dubbo:method name = "findXxx" timeout = "3000" retries = "2" />
</ dubbo:reference >

<dubbo:argument/>

(+) (#)

方法參數配置:
配置類:com.alibaba.dubbo.config.ArgumentConfig
說明:該標籤爲<dubbo:method>的子標籤,用於方法參數的特徵描述,好比:

< dubbo:method name = "findXxx" timeout = "3000" retries = "2" >
     < dubbo:argument index = "0" callback = "true" />
< dubbo:method >
標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:argument> index   int 必填   標識 方法名 2.0.6以上版本
<dubbo:argument> type   String 與index二選一   標識 經過參數類型查找參數的index 2.0.6以上版本
<dubbo:argument> callback <metodName><index>.retries boolean 可選   服務治理 參數是否爲callback接口,若是爲callback,服務提供方將生成反向代理,能夠從服務提供方反向調用消費方,一般用於事件推送. 2.0.6以上版本

<dubbo:parameter/>

(+) (#)

選項參數配置:
配置類:java.util.Map
說明:該標籤爲<dubbo:protocol>或<dubbo:service>或<dubbo:provider>或<dubbo:reference>或<dubbo:consumer>的子標籤,用於配置自定義參數,該配置項將做爲擴展點設置自定義參數使用。

標籤 屬性 對應URL參數 類型 是否必填 缺省值 做用 描述 兼容性
<dubbo:parameter> key key string 必填   服務治理 路由參數鍵 2.0.0以上版本
<dubbo:parameter> value value string 必填   服務治理 路由參數值 2.0.0以上版本

好比:

< dubbo:protocol name = "napoli" >
     < dubbo:parameter key = "http://10.20.160.198/wiki/display/dubbo/napoli.queue.name" value = "xxx" />
</ dubbo:protocol >

也能夠:

< dubbo:protocol name = "jms" p:queue = "xxx" />

詳細參見:自定義參數

協議參考手冊

(+) (#)

推薦使用Dubbo協議
性能測試報告
各協議的性能狀況,請參見:性能測試報告 (+)

dubbo://

(+) (#)

Dubbo缺省協議採用單一長鏈接和NIO異步通信,適合於小數據量大併發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的狀況。
Dubbo缺省協議不適合傳送大數據量的服務,好比傳文件,傳視頻等,除非請求量很低。
< dubbo:protocol name = "dubbo" port = "20880" />

Set default protocol:

< dubbo:provider protocol = "dubbo" />

Set service protocol:

< dubbo:service protocol = "dubbo" />

Multi port:

< dubbo:protocol id = "dubbo1" name = "dubbo" port = "20880" />
< dubbo:protocol id = "dubbo2" name = "dubbo" port = "20881" />

Dubbo protocol options:

< dubbo:protocol name=「dubbo」 port=「9090」 server=「netty」 client=「netty」 codec=「dubbo」 serialization=「hessian2」 charset=「UTF-8」 threadpool=「fixed」 threads=「100」 queues=「0」 iothreads=「9」 buffer=「8192」 accepts=「1000」 payload=「8388608」 />

  • Transporter
    • mina, netty, grizzy
  • Serialization
    • dubbo, hessian2, java, json
  • Dispatcher
    • all, direct, message, execution, connection
  • ThreadPool
    • fixed, cached
Dubbo協議缺省每服務每提供者每消費者使用單一長鏈接,若是數據量較大,能夠使用多個鏈接。
< dubbo:protocol name = "dubbo" connections = "2" />
  • <dubbo:service connections=」0」>或<dubbo:reference connections=」0」>表示該服務使用JVM共享長鏈接。(缺省)
  • <dubbo:service connections=」1」>或<dubbo:reference connections=」1」>表示該服務使用獨立長鏈接。
  • <dubbo:service connections=」2」>或<dubbo:reference connections=」2」>表示該服務使用獨立兩條長鏈接。
爲防止被大量鏈接撐掛,可在服務提供方限制大接收鏈接數,以實現服務提供方自我保護。
< dubbo:protocol name = "dubbo" accepts = "1000" />

缺省協議,使用基於mina1.1.7+hessian3.2.1的tbremoting交互。

  • 鏈接個數:單鏈接
  • 鏈接方式:長鏈接
  • 傳輸協議:TCP
  • 傳輸方式:NIO異步傳輸
  • 序列化:Hessian二進制序列化
  • 適用範圍:傳入傳出參數數據包較小(建議小於100K),消費者比提供者個數多,單一消費者沒法壓滿提供者,儘可能不要用dubbo協議傳輸大文件或超大字符串
  • 適用場景:常規遠程服務方法調用

爲何要消費者比提供者個數多:
因dubbo協議採用單一長鏈接,
假設網絡爲千兆網卡(1024Mbit=128MByte),
根據測試經驗數據每條鏈接最多隻能壓滿7MByte(不一樣的環境可能不同,供參考),
理論上1個服務提供者須要20個服務消費者才能壓滿網卡。

爲何不能傳大包:
因dubbo協議採用單一長鏈接,
若是每次請求的數據包大小爲500KByte,假設網絡爲千兆網卡(1024Mbit=128MByte),每條鏈接最大7MByte(不一樣的環境可能不同,供參考),
單個服務提供者的TPS(每秒處理事務數)最大爲:128MByte / 500KByte = 262。
單個消費者調用單個服務提供者的TPS(每秒處理事務數)最大爲:7MByte / 500KByte = 14。
若是能接受,能夠考慮使用,不然網絡將成爲瓶頸。

爲何採用異步單一長鏈接:
由於服務的現狀大都是服務提供者少,一般只有幾臺機器,
而服務的消費者多,可能整個網站都在訪問該服務,
好比Morgan的提供者只有6臺提供者,卻有上百臺消費者,天天有1.5億次調用,
若是採用常規的hessian服務,服務提供者很容易就被壓跨,
經過單一鏈接,保證單一消費者不會壓死提供者,
長鏈接,減小鏈接握手驗證等,
並使用異步IO,複用線程池,防止C10K問題。

(1) 約束:

  • 參數及返回值需實現Serializable接口
  • 參數及返回值不能自定義實現List, Map, Number, Date, Calendar等接口,只能用JDK自帶的實現,由於hessian會作特殊處理,自定義實現類中的屬性值都會丟失。()
  • Hessian序列化,只傳成員屬性值和值的類型,不傳方法或靜態變量,兼容狀況:(由吳亞軍提供)
    數據通信 狀況 結果
    A->B 類A多一種 屬性(或者說類B少一種 屬性) 不拋異常,A多的那 個屬性的值,B沒有, 其餘正常
    A->B 枚舉A多一種 枚舉(或者說B少一種 枚舉),A使用多 出來的枚舉進行傳輸 拋異常
    A->B 枚舉A多一種 枚舉(或者說B少一種 枚舉),A不使用 多出來的枚舉進行傳輸 不拋異常,B正常接 收數據
    A->B A和B的屬性 名相同,但類型不相同 拋異常
    A->B serialId 不相同 正常傳輸

    總結:會拋異常的狀況:枚 舉值一邊多一種,一邊少一種,正好使用了差異的那種,或者屬性名相同,類型不一樣

接口增長方法,對客戶端無影響,若是該方法不是客戶端須要的,客戶端不須要從新部署;
輸入參數和結果集中增長屬性,對客戶端無影響,若是客戶端並不須要新屬性,不用從新
部署;
輸入參數和結果集屬性名變化,對客戶端序列化無影響,可是若是客戶端不從新部署,無論輸入仍是輸出,屬性名變化的屬性值是獲取不到的。
總結:服務器端和客戶端對領域對象並不須要徹底一致,而是按照最大匹配原則。

(2) 配置:
dubbo.properties:

dubbo.service.protocol=dubbo

rmi://

(+) (#)

RMI協議採用JDK標準的java.rmi.*實現,採用阻塞式短鏈接和JDK標準序列化方式。
若是正在使用RMI提供服務給外部訪問(公司內網環境應該不會有攻擊風險),同時應用裏依賴了老的common-collections包(dubbo不會依賴這個包,請排查本身的應用有沒有使用)的狀況下,存在反序列化安全風險。
請檢查應用:
將commons-collections3 請升級到3.2.2版本:https://commons.apache.org/proper/commons-collections/release_3_2_2.html
將commons-collections4 請升級到4.1版本:https://commons.apache.org/proper/commons-collections/release_4_1.html
新版本的commons-collections解決了該問題
  • 若是服務接口繼承了java.rmi.Remote接口,能夠和原生RMI互操做,即:
    • 提供者用Dubbo的RMI協議暴露服務,消費者直接用標準RMI接口調用,
    • 或者提供方用標準RMI暴露服務,消費方用Dubbo的RMI協議調用。
  • 若是服務接口沒有繼承java.rmi.Remote接口,
    • 缺省Dubbo將自動生成一個com.xxx.XxxService$Remote的接口,並繼承java.rmi.Remote接口,並以此接口暴露服務,
    • 但若是設置了<dubbo:protocol name="rmi" codec="spring" />,將不生成$Remote接口,而使用Spring的RmiInvocationHandler接口暴露服務,和Spring兼容。

Define rmi protocol:

< dubbo:protocol name = "rmi" port = "1099" />

Set default protocol:

< dubbo:provider protocol = "rmi" />

Set service protocol:

< dubbo:service protocol = "rmi" />

Multi port:

< dubbo:protocol id = "rmi1" name = "rmi" port = "1099" />
< dubbo:protocol id = "rmi2" name = "rmi" port = "2099" />
 
< dubbo:service protocol = "rmi1" />

Spring compatible:

< dubbo:protocol name = "rmi" codec = "spring" />

Java標準的遠程調用協議。

  • 鏈接個數:多鏈接
  • 鏈接方式:短鏈接
  • 傳輸協議:TCP
  • 傳輸方式:同步傳輸
  • 序列化:Java標準二進制序列化
  • 適用範圍:傳入傳出參數數據包大小混合,消費者與提供者個數差很少,可傳文件。
  • 適用場景:常規遠程服務方法調用,與原生RMI服務互操做

(1) 約束:

  • 參數及返回值需實現Serializable接口
  • dubbo配置中的超時時間對rmi無效,需使用java啓動參數設置:-Dsun.rmi.transport.tcp.responseTimeout=3000,參見下面的RMI配置。

(2) 配置:
dubbo.properties:

dubbo.service.protocol=rmi

(3) RMI配置:

java -Dsun.rmi.transport.tcp.responseTimeout= 3000

更多RMI優化參數請查看:
http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/guides/rmi/sunrmiproperties.html

hessian://

(+) (#)

Hessian協議用於集成Hessian的服務,Hessian底層採用Http通信,採用Servlet暴露服務,Dubbo缺省內嵌Jetty做爲服務器實現。
Hessian是Caucho開源的一個RPC框架:http://hessian.caucho.com,其通信效率高於WebService和Java自帶的序列化。

依賴:

< dependency >
     < groupId >com.caucho</ groupId >
     < artifactId >hessian</ artifactId >
     < version >4.0.7</ version >
</ dependency >

能夠和原生Hessian服務互操做,即:

  • 提供者用Dubbo的Hessian協議暴露服務,消費者直接用標準Hessian接口調用,
  • 或者提供方用標準Hessian暴露服務,消費方用Dubbo的Hessian協議調用。

基於Hessian的遠程調用協議。

  • 鏈接個數:多鏈接
  • 鏈接方式:短鏈接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:Hessian二進制序列化
  • 適用範圍:傳入傳出參數數據包較大,提供者比消費者個數多,提供者壓力較大,可傳文件。
  • 適用場景:頁面傳輸,文件傳輸,或與原生hessian服務互操做

(1) 約束:

  • 參數及返回值需實現Serializable接口
  • 參數及返回值不能自定義實現List, Map, Number, Date, Calendar等接口,只能用JDK自帶的實現,由於hessian會作特殊處理,自定義實現類中的屬性值都會丟失。

(2) 配置:
Define hessian protocol:

< dubbo:protocol name = "hessian" port = "8080" server = "jetty" />

Set default protocol:

< dubbo:provider protocol = "hessian" />

Set service protocol:

< dubbo:service protocol = "hessian" />

Multi port:

< dubbo:protocol id = "hessian1" name = "hessian" port = "8080" />
< dubbo:protocol id = "hessian2" name = "hessian" port = "8081" />

Directly provider:

< dubbo:reference id = "helloService" interface = "HelloWorld" url = "hessian://10.20.153.10:8080/helloWorld" />

h4. Jetty Server: (default)

< dubbo:protocol ... server = "jetty" />

h4. Servlet Bridge Server: (recommend)

< dubbo:protocol ... server = "servlet" />

web.xml:

< servlet >
          < servlet-name >dubbo</ servlet-name >
          < servlet-class >com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</ servlet-class >
          < load-on-startup >1</ load-on-startup >
</ servlet >
< servlet-mapping >
          < servlet-name >dubbo</ servlet-name >
          < url-pattern >/*</ url-pattern >
</ servlet-mapping >

注意,若是使用servlet派發請求:

  • 協議的端口<dubbo:protocol port="8080" />必須與servlet容器的端口相同,
  • 協議的上下文路徑<dubbo:protocol contextpath="foo" />必須與servlet應用的上下文路徑相同。

http://

(+) (#)

採用Spring的HttpInvoker實現
2.3.0以上版本支持

基於http表單的遠程調用協議。參見:[HTTP協議使用說明]

  • 鏈接個數:多鏈接
  • 鏈接方式:短鏈接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:表單序列化
  • 適用範圍:傳入傳出參數數據包大小混合,提供者比消費者個數多,可用瀏覽器查看,可用表單或URL傳入參數,暫不支持傳文件。
  • 適用場景:需同時給應用程序和瀏覽器JS使用的服務。

(1) 約束:

  • 參數及返回值需符合Bean規範

(2) 配置:
dubbo.xml:

<dubbo:protocol name= "http" port= "8080" />

h4. Jetty Server: (default)

< dubbo:protocol ... server = "jetty" />

h4. Servlet Bridge Server: (recommend)

< dubbo:protocol ... server = "servlet" />

web.xml:

< servlet >
          < servlet-name >dubbo</ servlet-name >
          < servlet-class >com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</ servlet-class >
          < load-on-startup >1</ load-on-startup >
</ servlet >
< servlet-mapping >
          < servlet-name >dubbo</ servlet-name >
          < url-pattern >/*</ url-pattern >
</ servlet-mapping >

注意,若是使用servlet派發請求:

  • 協議的端口<dubbo:protocol port="8080" />必須與servlet容器的端口相同,
  • 協議的上下文路徑<dubbo:protocol contextpath="foo" />必須與servlet應用的上下文路徑相同。

webservice://

(+) (#)

2.3.0以上版本支持。
基於CXF的frontend-simpletransports-http實現。
CXF是Apache開源的一個RPC框架:http://cxf.apache.org,由Xfire和Celtix合併而來 。

依賴:

< dependency >
     < groupId >org.apache.cxf</ groupId >
     < artifactId >cxf-rt-frontend-simple</ artifactId >
     < version >2.6.1</ version >
</ dependency >
< dependency >
     < groupId >org.apache.cxf</ groupId >
     < artifactId >cxf-rt-transports-http</ artifactId >
     < version >2.6.1</ version >
</ dependency >

能夠和原生WebService服務互操做,即:

  • 提供者用Dubbo的WebService協議暴露服務,消費者直接用標準WebService接口調用,
  • 或者提供方用標準WebService暴露服務,消費方用Dubbo的WebService協議調用。

基於WebService的遠程調用協議。

  • 鏈接個數:多鏈接
  • 鏈接方式:短鏈接
  • 傳輸協議:HTTP
  • 傳輸方式:同步傳輸
  • 序列化:SOAP文本序列化
  • 適用場景:系統集成,跨語言調用。

(1) 約束:

  • 參數及返回值需實現Serializable接口
  • 參數儘可能使用基本類型和POJO。

(2) 配置:
Define hessian protocol:

< dubbo:protocol name = "webservice" port = "8080" server = "jetty" />

Set default protocol:

< dubbo:provider protocol = "webservice" />

Set service protocol:

< dubbo:service protocol = "webservice" />

Multi port:

< dubbo:protocol id = "webservice1" name = "webservice" port = "8080" />
< dubbo:protocol id = "webservice2" name = "webservice" port = "8081" />

Directly provider:

< dubbo:reference id = "helloService" interface = "HelloWorld" url = "webservice://10.20.153.10:8080/com.foo.HelloWorld" />

WSDL:

h4. Jetty Server: (default)

< dubbo:protocol ... server = "jetty" />

h4. Servlet Bridge Server: (recommend)

< dubbo:protocol ... server = "servlet" />

web.xml:

< servlet >
          < servlet-name >dubbo</ servlet-name >
          < servlet-class >com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</ servlet-class >
          < load-on-startup >1</ load-on-startup >
</ servlet >
< servlet-mapping >
          < servlet-name >dubbo</ servlet-name >
          < url-pattern >/*</ url-pattern >
</ servlet-mapping >

注意,若是使用servlet派發請求:

  • 協議的端口<dubbo:protocol port="8080" />必須與servlet容器的端口相同,
  • 協議的上下文路徑<dubbo:protocol contextpath="foo" />必須與servlet應用的上下文路徑相同。

thrift://

(+) (#)

2.3.0以上版本支持。
Thrift說明
Thrift是Facebook捐給Apache的一個RPC框架,參見:http://thrift.apache.org
dubbo thrift協議
當前 dubbo 支持的 thrift 協議是對 thrift 原生協議的擴展,在原生協議的基礎上添加了一些額外的頭信息,好比service name,magic number等。使用dubbo thrift協議一樣須要使用thrift的idl compiler編譯生成相應的java代碼,後續版本中會在這方面作一些加強。

示例:https://github.com/alibaba/dubbo/tree/master/dubbo-rpc/dubbo-rpc-thrift/src/test/java/com/alibaba/dubbo/rpc/protocol/thrift/examples

依賴:

< dependency >
     < groupId >org.apache.thrift</ groupId >
     < artifactId >libthrift</ artifactId >
     < version >0.8.0</ version >
</ dependency >

全部服務共用一個端口:(與原生Thrift不兼容)

<dubbo:protocol name= "thrift" port= "3030" />

Thrift不支持數據類型:

  • null值 (不能在協議中傳遞null值)

memcached://

(+) (#)

2.3.0以上版本支持。
Memcached說明
Memcached是一個高效的KV緩存服務器,參見:http://memcached.org/

能夠經過腳本或監控中心手工填寫表單註冊memcached服務的地址:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash" ));

而後在客戶端使用時,不須要感知Memcached的地址:

< dubbo:reference id = "cache" interface = "http://10.20.160.198/wiki/display/dubbo/java.util.Map" group = "member" />

或者,點對點直連:

< dubbo:reference id = "cache" interface = "http://10.20.160.198/wiki/display/dubbo/java.util.Map" url = "memcached://10.20.153.10:11211" />

也能夠使用自定義接口:

< dubbo:reference id = "cache" interface = "com.foo.CacheService" url = "memcached://10.20.153.10:11211" />

方法名建議和memcached的標準方法名相同,即:get(key), set(key, value), delete(key)。

若是方法名和memcached的標準方法名不相同,則須要配置映射關係:(其中"p:xxx"爲spring的標準p標籤)

< dubbo:reference id = "cache" interface = "com.foo.CacheService" url = "memcached://10.20.153.10:11211" p:set = "putFoo" p:get = "getFoo" p:delete = "removeFoo" />

redis://

(+) (#)

2.3.0以上版本支持。
Redis說明
Redis是一個高效的KV存儲服務器,參見:http://redis.io

能夠經過腳本或監控中心手工填寫表單註冊redis服務的地址:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory. class ).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf( "zookeeper://10.20.153.10:2181" ));
registry.register(URL.valueOf( "redis://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo&group=member&loadbalance=consistenthash" ));

而後在客戶端使用時,不須要感知Redis的地址:

< dubbo:reference id = "store" interface = "http://10.20.160.198/wiki/display/dubbo/java.util.Map" group = "member" />

或者,點對點直連:

< dubbo:reference id = "store" interface = "http://10.20.160.198/wiki/display/dubbo/java.util.Map" url = "redis://10.20.153.10:6379" />

也能夠使用自定義接口:

< dubbo:reference id = "store" interface = "com.foo.StoreService" url = "redis://10.20.153.10:6379" />

方法名建議和redis的標準方法名相同,即:get(key), set(key, value), delete(key)。

若是方法名和redis的標準方法名不相同,則須要配置映射關係:(其中"p:xxx"爲spring的標準p標籤)

< dubbo:reference id = "cache" interface = "com.foo.CacheService" url = "memcached://10.20.153.10:11211" p:set = "putFoo" p:get = "getFoo" p:delete = "removeFoo" />

註冊中心參考手冊

(+) (#)

推薦使用Zookeeper註冊中心

Multicast註冊中心

(+) (#)

不須要啓動任何中心節點,只要廣播地址同樣,就能夠互相發現
組播受網絡結構限制,只適合小規模應用或開發階段使用。
組播地址段: 224.0.0.0 - 239.255.255.255

  1. 提供方啓動時廣播本身的地址。
  2. 消費方啓動時廣播訂閱請求。
  3. 提供方收到訂閱請求時,單播本身的地址給訂閱者,若是設置了unicast=false,則廣播給訂閱者。
  4. 消費方收到提供方地址時,鏈接該地址進行RPC調用。
< dubbo:registry address = "multicast://224.5.6.7:1234" />

Or:

< dubbo:registry protocol = "multicast" address = "224.5.6.7:1234" />

爲了減小廣播量,Dubbo缺省使用單播發送提供者地址信息給消費者,
若是一個機器上同時啓了多個消費者進程,消費者需聲明unicast=false,不然只會有一個消費者能收到消息:

< dubbo:registry address = "multicast://224.5.6.7:1234?unicast=false" />

Or:

< dubbo:registry protocol = "multicast" address = "224.5.6.7:1234" >
     < dubbo:parameter key = "unicast" value = "false" />
</ dubbo:registry >

Zookeeper註冊中心

(+) (#)

建議使用dubbo-2.3.3以上版本的zookeeper註冊中心客戶端
Zookeeper說明
Zookeeper是Apacahe Hadoop的子項目,是一個樹型的目錄服務,支持變動推送,適合做爲Dubbo服務的註冊中心,工業強度較高,可用於生產環境,並推薦使用,參見:http://zookeeper.apache.org
Zookeeper安裝
安裝方式參見: Zookeeper安裝手冊,只需搭一個原生的Zookeeper服務器,並將Quick Start中Provider和Consumer裏的conf/dubbo.properties中的dubbo.registry.addrss的值改成zookeeper://127.0.0.1:2181便可使用
可靠性聲明
阿里內部並無採用Zookeeper作爲註冊中心,而是使用本身實現的基於數據庫的註冊中心,即:Zookeeper註冊中心並無在阿里內部長時間運行的可靠性保障,此Zookeeper橋接實現只爲開源版本提供,其可靠性依賴於Zookeeper自己的可靠性。
兼容性聲明
因2.0.8最初設計的zookeeper存儲結構不能擴充不一樣類型的數據,2.0.9版本作了調整,因此不兼容,需所有改用2.0.9版本才行,之後的版本會保持兼容2.0.9。
2.2.0版本改成基於zkclient實現,需增長zkclient的依賴包,2.3.0版本增長了基於curator的實現,做爲可選實現策略。

流程說明:

  • 服務提供者啓動時
    • 向/dubbo/com.foo.BarService/providers目錄下寫入本身的URL地址。
  • 服務消費者啓動時
    • 訂閱/dubbo/com.foo.BarService/providers目錄下的提供者URL地址。
    • 並向/dubbo/com.foo.BarService/consumers目錄下寫入本身的URL地址。
  • 監控中心啓動時
    • 訂閱/dubbo/com.foo.BarService目錄下的全部提供者和消費者URL地址。

支持如下功能:

  • 當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者信息。
  • 當註冊中心重啓時,能自動恢復註冊數據,以及訂閱請求。
  • 當會話過時時,能自動恢復註冊數據,以及訂閱請求。
  • 當設置<dubbo:registry check="false" />時,記錄失敗註冊和訂閱請求,後臺定時重試。
  • 可經過<dubbo:registry username="admin" password="1234" />設置zookeeper登陸信息。
  • 可經過<dubbo:registry group="dubbo" />設置zookeeper的根節點,不設置將使用無根樹。
  • 支持*號通配符<dubbo:reference group="*" version="*" />,可訂閱服務的全部分組和全部版本的提供者。

在provider和consumer中增長zookeeper客戶端jar包依賴:

< dependency >
     < groupId >org.apache.zookeeper</ groupId >
     < artifactId >zookeeper</ artifactId >
     < version >3.3.3</ version >
</ dependency >

或直接下載:http://repo1.maven.org/maven2/org/apache/zookeeper/zookeeper

支持zkclient和curator兩種Zookeeper客戶端實現:

ZKClient Zookeeper Registry

從2.2.0版本開始缺省爲zkclient實現,以提高zookeeper客戶端的健狀性。

ZKClient是Datameer開源的一個Zookeeper客戶端實現,開源比較早,參見:https://github.com/sgroschupf/zkclient

缺省配置:

< dubbo:registry ... client = "zkclient" />

或:

dubbo.registry.client=zkclient

或:

zookeeper://10.20.153.10:2181?client=zkclient

需依賴:

< dependency >
     < groupId >com.github.sgroschupf</ groupId >
     < artifactId >zkclient</ artifactId >
     < version >0.1</ version >
</ dependency >

或直接下載:http://repo1.maven.org/maven2/com/github/sgroschupf/zkclient

Curator Zookeeper Registry

從2.3.0版本開始支持可選curator實現。

Curator是Netflix開源的一個Zookeeper客戶端實現,比較活躍,參見:https://github.com/Netflix/curator

若是須要改成curator實現,請配置:

< dubbo:registry ... client = "curator" />

或:

dubbo.registry.client=curator

或:

zookeeper://10.20.153.10:2181?client=curator

需依賴:

< dependency >
     < groupId >com.netflix.curator</ groupId >
     < artifactId >curator-framework</ artifactId >
     < version >1.1.10</ version >
</ dependency >

或直接下載:http://repo1.maven.org/maven2/com/netflix/curator/curator-framework

Zookeeper單機配置:

< dubbo:registry address = "zookeeper://10.20.153.10:2181" />

Or:

< dubbo:registry protocol = "zookeeper" address = "10.20.153.10:2181" />

Zookeeper集羣配置:

< dubbo:registry address = "zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181" />

Or:

< dubbo:registry protocol = "zookeeper" address = "10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181" />

同一Zookeeper,分紅多組註冊中心:

< dubbo:registry id = "chinaRegistry" protocol = "zookeeper" address = "10.20.153.10:2181" group = "china" />
< dubbo:registry id = "intlRegistry" protocol = "zookeeper" address = "10.20.153.10:2181" group = "intl" />

Redis註冊中心

(+) (#)

Redis說明
Redis是一個高效的KV存儲服務器,參見:http://redis.io
Redis安裝
安裝方式參見: Redis安裝手冊,只需搭一個原生的Redis服務器,並將Quick Start中Provider和Consumer裏的conf/dubbo.properties中的dubbo.registry.addrss的值改成redis://127.0.0.1:6379便可使用
Redis過時數據
經過心跳的方式檢測髒數據,服務器時間必須相同,而且對服務器有必定壓力。
可靠性聲明
阿里內部並無採用Redis作爲註冊中心,而是使用本身實現的基於數據庫的註冊中心,即:Redis註冊中心並無在阿里內部長時間運行的可靠性保障,此Redis橋接實現只爲開源版本提供,其可靠性依賴於Redis自己的可靠性。
從2.1.0版本開始支持

數據結構:

  • 使用Redis的Key/Map結構存儲數據。
    • 主Key爲服務名和類型。
    • Map中的Key爲URL地址。
    • Map中的Value爲過時時間,用於判斷髒數據,髒數據由監控中心刪除。(注意:服務器時間必需同步,不然過時檢測會不許確)
  • 使用Redis的Publish/Subscribe事件通知數據變動。
    • 經過事件的值區分事件類型:register, unregister, subscribe, unsubscribe。
    • 普通消費者直接訂閱指定服務提供者的Key,只會收到指定服務的register, unregister事件。
    • 監控中心經過psubscribe功能訂閱/dubbo/*,會收到全部服務的全部變動事件。

調用過程:

  1. 服務提供方啓動時,向Key:/dubbo/com.foo.BarService/providers下,添加當前提供者的地址。
  2. 並向Channel:/dubbo/com.foo.BarService/providers發送register事件。
  3. 服務消費方啓動時,從Channel:/dubbo/com.foo.BarService/providers訂閱register和unregister事件。
  4. 並向Key:/dubbo/com.foo.BarService/providers下,添加當前消費者的地址。
  5. 服務消費方收到register和unregister事件後,從Key:/dubbo/com.foo.BarService/providers下獲取提供者地址列表。
  6. 服務監控中心啓動時,從Channel:/dubbo/*訂閱register和unregister,以及subscribe和unsubsribe事件。
  7. 服務監控中心收到register和unregister事件後,從Key:/dubbo/com.foo.BarService/providers下獲取提供者地址列表。
  8. 服務監控中心收到subscribe和unsubsribe事件後,從Key:/dubbo/com.foo.BarService/consumers下獲取消費者地址列表。

選項:

  • 可經過<dubbo:registry group="dubbo" />設置redis中key的前綴,缺省爲dubbo。
  • 可經過<dubbo:registry cluster="replicate" />設置redis集羣策略,缺省爲failover。
    • failover: 只寫入和讀取任意一臺,失敗時重試另外一臺,須要服務器端自行配置數據同步。
    • replicate: 在客戶端同時寫入全部服務器,只讀取單臺,服務器端不須要同步,註冊中心集羣增大,性能壓力也會更大。

Config redis registry:

< dubbo:registry address = "redis://10.20.153.10:6379" />

Or:

< dubbo:registry address = "redis://10.20.153.10:6379?backup=10.20.153.11:6379,10.20.153.12:6379" />

Or:

< dubbo:registry protocol = "redis" address = "10.20.153.10:6379" />

Or:

< dubbo:registry protocol = "redis" address = "10.20.153.10:6379,10.20.153.11:6379,10.20.153.12:6379" />

Simple註冊中心

(+) (#)

Dogfooding
註冊中心自己就是一個普通的Dubbo服務,能夠減小第三方依賴,使總體通信方式一致。
適用性說明
此SimpleRegistryService只是簡單實現,不支持集羣,可做爲自定義註冊中心的參考,但不適合直接用於生產環境。

Export simple registry service:

<? xml version = "1.0" encoding = "UTF-8" ?>
     xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
 
     <!-- 當前應用信息配置 -->
     < dubbo:application name = "simple-registry" />
 
     <!-- 暴露服務協議配置 -->
     < dubbo:protocol port = "9090" />
 
     <!-- 暴露服務配置 -->
     < dubbo:service interface = "com.alibaba.dubbo.registry.RegistryService" ref = "registryService" registry = "N/A" ondisconnect = "disconnect" callbacks = "1000" >
         < dubbo:method name = "subscribe" >< dubbo:argument index = "1" callback = "true" /></ dubbo:method >
         < dubbo:method name = "unsubscribe" >< dubbo:argument index = "1" callback = "false" /></ dubbo:method >
     </ dubbo:service >
 
     <!-- 簡單註冊中心實現,可自行擴展實現集羣和狀態同步 -->
     < bean id = "registryService" class = "com.alibaba.dubbo.registry.simple.SimpleRegistryService" />
 
</ beans >

Reference the simple registry service:

< dubbo:registry address = "127.0.0.1:9090" />

Or:

< dubbo:service interface = "com.alibaba.dubbo.registry.RegistryService" group = "simple" version = "1.0.0" ... >
< dubbo:registry address = "127.0.0.1:9090" group = "simple" version = "1.0.0" />

Simple監控中心

(+) (#)

監控中心也是一個標準的Dubbo服務,能夠經過註冊中心發現,也能夠直連。

1.1 暴露一個簡單監控中心服務到註冊中心: (若是是用安裝包,不須要本身寫這個配置,若是是本身實現監控中心,則須要)

     xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
     
     <!-- 當前應用信息配置 -->
     < dubbo:application name = "simple-monitor" />
     
     <!-- 鏈接註冊中心配置 -->
     < dubbo:registry address = "127.0.0.1:9090" />
     
     <!-- 暴露服務協議配置 -->
     < dubbo:protocol port = "7070" />
     
     <!-- 暴露服務配置 -->
     < dubbo:service interface = "com.alibaba.dubbo.monitor.MonitorService" ref = "monitorService" />
     
     < bean id = "monitorService" class = "com.alibaba.dubbo.monitor.simple.SimpleMonitorService" />
     
</ beans >

1.2 經過註冊中心發現監控中心服務:

< dubbo:monitor protocol = "registry" />

或:

dubbo.properties
dubbo.monitor.protocol=registry

2.1 暴露一個簡單監控中心服務,但不註冊到註冊中心: (若是是用安裝包,不須要本身寫這個配置,若是是本身實現監控中心,則須要)

     xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd" >
     
     <!-- 當前應用信息配置 -->
     < dubbo:application name = "simple-monitor" />
     
     <!-- 暴露服務協議配置 -->
     < dubbo:protocol port = "7070" />
     
     <!-- 暴露服務配置 -->
     < dubbo:service interface = "com.alibaba.dubbo.monitor.MonitorService" ref = "monitorService" registry = "N/A" />
     
     < bean id = "monitorService" class = "com.alibaba.dubbo.monitor.simple.SimpleMonitorService" />
     
</ beans >

2.2 直連監控中心服務:

< dubbo:monitor address = "dubbo://127.0.0.1:7070/com.alibaba.dubbo.monitor.MonitorService" />

或:

< dubbo:monitor address = "127.0.0.1:7070" />

或:

dubbo.properties
dubbo.monitor.address= 127.0 . 0.1 : 7070

Telnet命令參考手冊

(+) (#)

Dubbo2.0.5以上版本服務提供端口支持telnet命令,
使用如:

telnet localhost 20880

或者:

echo status | nc -i 1 localhost 20880

telnet命令能夠擴展,參見:擴展參考手冊第6條。
status命令所檢查的資源也能夠擴展,參見:擴展參考手冊第5條。

ls

(list services and methods)

ls

顯示服務列表。

ls -l

顯示服務詳細信息列表。

ls XxxService

顯示服務的方法列表。

ls -l XxxService

顯示服務的方法詳細信息列表。

ps

(print server ports and connections)

ps

顯示服務端口列表。

ps -l

顯示服務地址列表。

ps 20880

顯示端口上的鏈接信息。

ps -l 20880

顯示端口上的鏈接詳細信息。

cd

(change default service)

cd XxxService

改變缺省服務,當設置了缺省服務,凡是須要輸入服務名做爲參數的命令,均可以省略服務參數。

cd /

取消缺省服務。

pwd

(print working default service)

pwd

顯示當前缺省服務。

trace

trace XxxService

跟蹤1次服務任意方法的調用狀況。

trace XxxService 10

跟蹤10次服務任意方法的調用狀況。

trace XxxService xxxMethod

跟蹤1次服務方法的調用狀況

trace XxxService xxxMethod 10

跟蹤10次服務方法的調用狀況。

count

count XxxService

統計1次服務任意方法的調用狀況。

count XxxService 10

統計10次服務任意方法的調用狀況。

count XxxService xxxMethod

統計1次服務方法的調用狀況。

count XxxService xxxMethod 10

統計10次服務方法的調用狀況。

invoke

invoke XxxService.xxxMethod({"prop": "value"})

調用服務的方法。

invoke xxxMethod({"prop": "value"})

調用服務的方法(自動查找包含此方法的服務)。

status

status

顯示彙總狀態,該狀態將彙總全部資源的狀態,當所有OK時則顯示OK,只要有一個ERROR則顯示ERROR,只要有一個WARN則顯示WARN。

status -l

顯示狀態列表。

log

2.0.6以上版本支持

log debug 
修改dubbo logger的日誌級別

log 100
查看file logger的最後100字符的日誌

help

help

顯示telnet命幫助信息。

help xxx

顯示xxx命令的詳細幫助信息。

clear

clear

清除屏幕上的內容。

clear 100

清除屏幕上的指定行數的內容。

exit

exit

退出當前telnet命令行。

Maven插件參考手冊

(+) (#)

mvn dubbo:registry

mvn dubbo:registry
以缺省的9090端口啓動一個簡易註冊中心

mvn dubbo:registry -Dport=9099
以指定的9099端口啓動一個簡易註冊中心

mvn dubbo:create

(還沒有發佈)

mvn dubbo:create
生成demo服務提供者應用

mvn dubbo:create -Dapplication=xxx -Dpackage=com.alibaba.xxx -Dservice=XxxService,YyyService -Dversion=1.0.0
生成指定接口和版本的服務提供者應用

服務化最佳實踐

(+) (#)

分包

  • 建議將服務接口,服務模型,服務異常等均放在API包中,由於服務模型及異常也是API的一部分,
    同時,這樣作也符合分包原則:重用發佈等價原則(REP),共同重用原則(CRP)
  • 若是須要,也能夠考慮在API包中放置一份spring的引用配置,這樣使用方,只需在Spring加載過程當中引用此配置便可,
    配置建議放在模塊的包目錄下,以避免衝突,如:com/alibaba/china/xxx/dubbo-reference.xml

粒度

  • 服務接口儘量大粒度,每一個服務方法應表明一個功能,而不是某功能的一個步驟,不然將面臨分佈式事務問題,Dubbo暫未提供分佈式事務支持。
  • 服務接口建議以業務場景爲單位劃分,並對相近業務作抽象,防止接口數量爆炸
  • 不建議使用過於抽象的通用接口,如:Map query(Map),這樣的接口沒有明確語義,會給後期維護帶來不便。

版本

  • 每一個接口都應定義版本號,爲後續不兼容升級提供可能,如:<dubbo:service interface="com.xxx.XxxService" version="1.0" />
  • 建議使用兩位版本號,由於第三位版本號一般表示兼容升級,只有不兼容時才須要變動服務版本。
  • 當不兼容時,先升級一半提供者爲新版本,再將消費者所有升爲新版本,而後將剩下的一半提供者升爲新版本。

兼容性

  • 服務接口增長方法,或服務模型增長字段,可向後兼容,刪除方法或刪除字段,將不兼容,枚舉類型新增字段也不兼容,需經過變動版本號升級。
  • 各協議的兼容性不一樣,參見: 服務協議

枚舉值

  • 若是是完備集,能夠用Enum,好比:ENABLE, DISABLE。
  • 若是是業務種類,之後明顯會有類型增長,不建議用Enum,能夠用String代替。
  • 若是是在返回值中用了Enum,並新增了Enum值,建議先升級服務消費方,這樣服務提供方不會返回新值。
  • 若是是在傳入參數中用了Enum,並新增了Enum值,建議先升級服務提供方,這樣服務消費方不會傳入新值。

序列化

  • 服務參數及返回值建議使用POJO對象,即經過set,get方法表示屬性的對象。
  • 服務參數及返回值不建議使用接口,由於數據模型抽象的意義不大,而且序列化須要接口實現類的元信息,並不能起到隱藏實現的意圖。
  • 服務參數及返回值都必需是byValue的,而不能是byRef的,消費方和提供方的參數或返回值引用並非同一個,只是值相同,Dubbo不支持引用遠程對象。

異常

  • 建議使用異常彙報錯誤,而不是返回錯誤碼,異常信息能攜帶更多信息,以及語義更友好,
  • 若是擔憂性能問題,在必要時,能夠經過override掉異常類的fillInStackTrace()方法爲空方法,使其不拷貝棧信息,
  • 查詢方法不建議拋出checked異常,不然調用方在查詢時將過多的try...catch,而且不能進行有效處理,
  • 服務提供方不該將DAO或SQL等異常拋給消費方,應在服務實現中對消費方不關心的異常進行包裝,不然可能出現消費方沒法反序列化相應異常。

調用

  • 不要只是由於是Dubbo調用,而把調用Try-Catch起來。Try-Catch應該加上合適的回滾邊界上。
  • 對於輸入參數的校驗邏輯在Provider端要有。若有性能上的考慮,服務實現者能夠考慮在API包上加上服務Stub類來完成檢驗。

推薦用法

(+) (#)

在Provider上儘可能多配置Consumer端屬性

緣由以下:

  1. 做服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等
  2. 在Provider配置後,Consumer不配置則會使用Provider的配置值,即Provider配置能夠做爲Consumer的缺省值。
    不然,Consumer會使用Consumer端的全局設置,這對於Provider不可控的,而且每每是不合理的
    PS: 配置的覆蓋規則:1) 方法級配置別優於接口級別,即小Scope優先 2) Consumer端配置 優於 Provider配置 優於 全局配置,最後是Dubbo Hard Code的配置值(見配置文檔)
    配置的覆蓋規則詳見: Dubbo配置參考手冊

Provider上儘可能多配置Consumer端的屬性,讓Provider實現者一開始就思考Provider服務特色、服務質量的問題。

示例:

< dubbo:service interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" ref = "helloService"
     timeout = "300" retry = "2" loadbalance = "random" actives = "0"
/>
 
< dubbo:service interface = "com.alibaba.hello.api.WorldService" version = "1.0.0" ref = "helloService"
     timeout = "300" retry = "2" loadbalance = "random" actives = "0" >
     < dubbo:method name = "findAllPerson" timeout = "10000" retries = "9" loadbalance = "leastactive" actives = "5" />
< dubbo:service />

在Provider能夠配置的Consumer端屬性有:

  1. timeout,方法調用超時
  2. retries,失敗重試次數,缺省是2(表示加上第一次調用,會調用3次)
  3. loadbalance,負載均衡算法(有多個Provider時,如何挑選Provider調用),缺省是隨機(random)。
    還能夠有輪訓(roundrobin)、最不活躍優先(leastactive,指從Consumer端併發調用最好的Provider,能夠減小的反應慢的Provider的調用,由於反應更容易累積併發的調用)
  4. actives,消費者端,最大併發調用限制,即當Consumer對一個服務的併發調用到上限後,新調用會Wait直到超時。
    在方法上配置(dubbo:method )則併發限制針對方法,在接口上配置(dubbo:service),則併發限制針對服務。

詳細配置說明參見:Dubbo配置參考手冊 

Provider上配置合理的Provider端屬性

< dubbo:protocol threads = "200" />
 
< dubbo:service interface = "com.alibaba.hello.api.HelloService" version = "1.0.0" ref = "helloService"
     executes = "200" >
     < dubbo:method name = "findAllPerson" executes = "50" />
</ dubbo:service >

Provider上能夠配置的Provider端屬性有:

  1. threads,服務線程池大小
  2. executes,一個服務提供者並行執行請求上限,即當Provider對一個服務的併發調用到上限後,新調用會Wait(Consumer可能到超時)。在方法上配置(dubbo:method )則併發限制針對方法,在接口上配置(dubbo:service),則併發限制針對服務。

配置上管理信息

目前有負責人信息和組織信息(用於區分站點)。

有問題時便於的找到服務的負責人,至少寫兩我的以便備份。

負責人和組織的信息能夠在註冊中心的上看到。

示例:

應用配置負責人、組織
< dubbo:application owner=」ding.lid,william.liangf」 organization=」intl」 />
service配置負責人
< dubbo:service owner=」ding.lid,william.liangf」 />
reference配置負責人
< dubbo:reference owner=」ding.lid,william.liangf」 />

dubbo:service、dubbo:reference沒有配置負責人,則使用dubbo:application設置的負責人。

配置上Dubbo緩存文件

配置方法以下:

提供者列表緩存文件
< dubbo:registry file=」${user.home}/output/dubbo.cache」 />

注意:

  1. 文件的路徑,應用能夠根據須要調整,保證這個文件不會在發佈過程當中被清除。
  2. 若是有多個應用進程注意不要使用同一個文件,避免內容被覆蓋

這個文件會緩存:

  1. 註冊中心的列表
  2. 服務提供者列表

有了這項配置後,當應用重啓過程當中,Dubbo註冊中心不可用時則應用會從這個緩存文件讀取服務提供者列表的信息,進一步保證應用可靠性。

監控配置

1. 使用固定端口暴露服務,而不要使用隨機端口

這樣在註冊中心推送有延遲的狀況下,消費者經過緩存列表也能調用到原地址,保證調用成功。

3. 使用Dragoon的http監控項監控註冊中心上服務提供方

Dragoon監控服務在註冊中心上的狀態:http://dubbo-reg1.hst.xyi.cn.alidc.net:8080/status/com.alibaba.morgan.member.MemberService:1.0.5,確保註冊中心上有該服務的存在。

4. 服務提供方,使用Dragoon的telnet或shell監控項

監控服務提供者端口狀態:echo status | nc --i 1 20880 | grep OK | wc --l,其中的20880爲服務端口

5. 服務消費方,經過將服務強制轉型爲EchoService,並調用$echo()測試該服務的提供者是可用

如 assertEqauls(「OK」, ((EchoService)memberService).$echo(「OK」));

不要使用dubbo.properties文件配置,推薦使用對應XML配置

Dubbo2中全部的配置項均可以Spring配置中,而且能夠針對單個服務配置。

# 如徹底不配置使用Dubbo缺省值,參見Dubbo配置參考手冊中的說明。

在Dubbo1中須要在dubbo.properties文件中的配置項,Dubbo2中配置示例以下:

1. 應用名 
<dubbo:application name= "myalibaba" >

對應dubbo.properties中的Key名dubbo.application.name

2. 註冊中心地址
<dubbo:registry address= "11.22.33.44:9090" >

對應dubbo.properties中的Key名dubbo.registry.address

3. 調用超時

能夠在多個配置項設置超時,由上至下覆蓋(即上面的優先),示例以下:

# 其它的參數(retries、loadbalance、actives等)的覆蓋策略也同樣。

提供者端特定方法的配置

<dubbo:service interface = "com.alibaba.xxx.XxxService" >
     <dubbo:method name= "findPerson" timeout= "1000" />
</dubbo:service>

提供者端特定接口的配置

<dubbo:service interface = "com.alibaba.xxx.XxxService" timeout= "200" />

# timeout能夠在多處設置,配置項及覆蓋規則詳見: Dubbo配置參考手冊

全局配置項值,對應dubbo.properties中的Key名dubbo.service.invoke.timeout

5. 服務提供者協議、服務的監聽端口
<dubbo:protocol name= "dubbo" port= "20880" />

對應dubbo.properties中的Key名dubbo.service.protocol、dubbo.service.server.port

4. 服務線程池大小
<dubbo:protocol threads= "100" />

對應dubbo.properties中的Key名dubbo.service.max.thread.threads.size

6. 消費者啓動時,沒有提供者是否拋異常Fast-Fail
<dubbo:reference interface = "com.alibaba.xxx.XxxService" check= "false" />

對應dubbo.properties中的Key名alibaba.intl.commons.dubbo.service.allow.no.provider

容量規劃

(+) (#)

如下數據供參考:

使用Dubbo的會員服務項目

  • 天天接收4億次遠程調用
  • 使用12臺網站標配機器提供服務(8核CPU,8G內存)
  • 平均負載在1如下(對於8核CPU負載很低)
  • 平均響應時間2.3到2.5毫秒,網絡開銷約佔1.5到1.6毫秒(和數據包大小有關)

使用Dubbo的產品受權服務項目

  • 天天接收3億次遠程調用
  • 使用8臺網站標配機器提供服務(8核CPU,8G內存)
  • 平均負載在1如下(對於8核CPU負載很低)
  • 平均響應時間1.4到2.8毫秒,網絡開銷約佔1.0到1.1毫秒(和數據包大小有關)

基準測試工具包

(+) (#)

下載benchmark壓縮包,並解壓

dubbo.benchmark-2.0.14.tar.gz

閱讀ReadMe.txt(內容以下,請以壓縮包內的爲準)

1、新建一個benchmark工程,如demo.benchmark
2、導入本身服務的接口api包和dubbo.benchmark.jar(解壓dubbo.benchmark.tar.gz,在lib目錄下)
3、新建一個類,實現AbstractClientRunnable
a、實現父類的構造函數
b、實現invoke方法,經過serviceFactory建立本地接口代理,並實現本身的業務邏輯,以下

public Object invoke(ServiceFactory serviceFactory) {
         DemoService demoService = (DemoService) serviceFactory.get(DemoService. class );
         return demoService.sendRequest( "hello" );
     }

4、將本身的benchmark工程打成jar包,如demo.benchmark.jar
5、將demo.benchmark.jar 和服務的api包放到dubbo.benchmark/lib目錄下
6、配置duubo.properties
7、運行run.bat(windows)或run.sh(linux)

如想測試dubbo的不一樣版本,直接替換lib下的dubbo的jar包便可。

性能測試報告

(+) (#)

測試說明

a、本次性能測試,測試了dubbo2.0全部支持的協議在不一樣大小和數據類型下的表現,並與dubbo1.0進行了對比。

b、總體性能相比1.0有了提高,平均提高10%,使用dubbo2.0新增的dubbo序列化還能得到10%~50%的性能提高,詳見下面的性能數據。

c、穩定性測試中因爲將底層通訊框架從mina換成netty,old區對象的增加大大減小,50小時運行,增加不到200m,無fullgc。(能夠確認爲mina在高併發下的設計缺陷)

d、存在的問題:在50k數據的時候2.0性能不如1.0,懷疑多是緩衝區設置的問題,下版本會進一步確認。 

測試環境

2.1 硬件部署與參數調整

主機/ip
硬件配置
操做系統及參數調整

10.20.153.11   機型 Tecal BH620
CPU model name : Intel(R) Xeon(R) CPU           E5520  @ 2.27GHz cache size : 8192 KB processor_count : 16
內存 Total System Memory: 6G Hardware Memory Info:  Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown
網絡 Total System Memory: 6G Hardware Memory Info:  Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown
磁盤 /dev/sda: 597.9 GB,   2.6.18-128.el5xen x86_64
10.20.153.10   機型 Tecal BH620
CPU model name : Intel(R) Xeon(R) CPU           E5520  @ 2.27GHz cache size : 8192 KB processor_count : 16
內存 Total System Memory: 6G Hardware Memory Info:  Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown Size: 4096MB, 1066MHz(0.9ns) Size: NoModule, Unknown
網絡 eth0: Link is up at 1000 Mbps, full duplex. peth0: Link is up at 1000 Mbps, full duplex.
磁盤 /dev/sda: 597.9 GB,   2.6.18-128.el5xen x86_64

 

2.2 軟件架構

主機/ip
軟件名稱及版本
關鍵參數

  java version "1.6.0_18" Java(TM) SE Runtime Environment (build 1.6.0_18-b07) Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode) -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
  jboss-4.0.5.GA  
  httpd-2.0.61 KeepAlive On MaxKeepAliveRequests 100000 KeepAliveTimeout 180 MaxRequestsPerChild 1000000 <IfModule worker.c>         StartServers 5         MaxClients 1024         MinSpareThreads 25         MaxSpareThreads 75         ThreadsPerChild 64         ThreadLimit 128         ServerLimit 16 </IfModule>

 

測試目的

 

3.1 指望性能指標(量化)

場景名稱
對應指標名稱
指望值範圍
實際值
是否知足指望(是/否)

1k數據  響應時間  0.9ms  0.79ms  是 
1k數據  TPS  10000  11994  是 

 

3.2 指望運行情況(非量化,可選)

2.0性能不低於1.0,2.0和1.0互調用的性能無明顯降低。 除了50k string其他皆經過
JVM內存運行穩定,無OOM,堆內存中無不合理的大對象的佔用。經過
CPU、內存、網絡、磁盤、文件句柄佔用平穩。經過
無頻繁線程鎖,線程數平穩。經過
業務線程負載均衡。經過
 

測試腳本

一、性能測試場景(10併發)

a、傳入1kString,不作任何處理,原樣返回

b、傳入50kString,不作任何處理,原樣返回

c、傳入200kString,不作任何處理,原樣返回

d、傳入1k pojo(嵌套的複雜person對象),不作任何處理,原樣返回

上述場景在dubbo1.0\dubbo2.0(hessian2序列化)\dubbo2.0(dubbo序列化)\rmi\hessian3.2.0\http(json序列化)進行10分鐘的性能測試。 主要考察序列化和網絡IO的性能,所以服務端無任何業務邏輯。取10併發是考慮到http協議在高併發下對CPU的使用率較高可能會先打到瓶頸。 

二、併發場景(20併發)

傳入1kString,在服務器段循環1w次,每次從新生成一個隨機數而後進行拼裝。

考察業務線程是否可以分配到每一個CPU上。 

三、穩定性場景(20併發)

同時調用1個參數爲String(5k)方法,1個參數爲person對象的方法,1個參數爲map(值爲3個person)的方法,持續運行50小時。 

四、高壓力場景(20併發)

在穩定性場景的基礎上,將提供者和消費者佈置成均爲2臺(一臺機器2個實例),且String的參數從20byte到200k,每隔10分鐘隨機變換。 

測試結果

5.1 場景名稱:pojo 場景

  TPS成功平均值  響應時間成功平均值(ms) 
dubbo1 
(hessian2序列化+mina) 
10813.5  0.9 
dubbo2 
(hessian2序列化+netty) 
11994  0.79 
dubbo2 
(dubbo序列化+netty) 
13620  0.67 
rmi  2461.79 
hessian  2417.7  4.1 
http(json序列化)  8179.08  1.15 
2.0和1.0默認 
對比百分比 
10.92  -12.22 
dubbo序列化相比hessian2序列化百分比  13.56  -15.19 

 

5.2 場景名稱:1k string 場景  |

   TPS成功平均值  響應時間成功平均值(ms) 
dubbo1 
(hessian2序列化+mina) 
11940  0.8 
dubbo2 
(hessian2序列化+netty) 
14402  0.64 
dubbo2 
(dubbo序列化+netty) 
15096  0.6 
rmi  11136.02  0.81 
hessian  11426.83  0.79 
http(json序列化)  8919.27  1.04 
2.0和1.0默認 
對比百分比 
20.62  -20.00 
dubbo序列化相比hessian2序列化百分比  4.82  -6.25 

 

5.3 場景名稱:50k string場景  |

   TPS成功平均值  響應時間成功平均值(ms) 
dubbo1 
(hessian2序列化+mina) 
1962.7  5.1 
dubbo2 
(hessian2序列化+netty) 
1293  5.03 
dubbo2 
(dubbo序列化+netty) 
1966  7.68 
rmi  3349.88  2.9 
hessian  1925.33  5.13 
http(json序列化)  3247.1 
2.0和1.0默認 
對比百分比 
-34.12  -1.37 
dubbo序列化相比hessian2序列化百分比  52.05  52.68 

 

5.4 場景名稱:200k string 場景  |

  TPS成功平均值  響應時間成功平均值(ms) 
dubbo1 
(hessian2序列化+mina) 
324.2  30.8 
dubbo2 
(hessian2序列化+netty) 
362.92  27.49 
dubbo2 
(dubbo序列化+netty) 
569.5  17.51 
rmi  1031.28  9.61 
hessian  628.06  15.83 
http(json序列化)  1011.97  9.79 
2.0和1.0默認 
對比百分比 
11.94  -10.75 
dubbo序列化相比hessian2序列化百分比  56.92  -36.30 

 

測試分析

 

6.1 性能分析評估

  Dubbo2.0的性能測試結論爲經過,從性能、內存佔用和穩定性上都有了提升和改進。由其是內存管理因爲將mina換成netty,大大減小了1.0版本在高併發大數據下的內存大鋸齒。以下圖:

6.2 性能對比分析(新舊環境、不一樣數據量級等)

Dubbo2.0相比較Dubbo1.0(默認使用的都是hessian2序列化)性能均有提高(除了50k String),詳見第五章的性能數據。

出於兼容性考慮默認的序列化方式和1.0保持一導致用hessian2,如對性能有更高要求能夠使用dubbo序列化,由其是在處理複雜對象時,在大數據量下能得到50%的提高(但此時已不建議使用Dubbo協議)。

Dubbo的設計目的是爲了知足高併發小數據量的rpc調用,在大數據量下的性能表現並很差,建議使用rmi或http協議。

6.3 測試侷限性分析(可選)

本次性能測試考察的是dubbo自己的性能,實際使用過程當中的性能有待應用來驗證。

因爲dubbo自己的性能佔用都在毫秒級,佔的基數很小,性能提高可能對應用總體的性能變化不大

因爲郵件篇幅所限沒有列出全部的監控圖,如需得到可在大力神平臺上查詢。

測試覆蓋率報告

(+) (#)

統計於 2012-02-03 (2.0.12)





Labels:
None
 
 
from: http://dubbo.io/User+Guide-zh.htm
相關文章
相關標籤/搜索