dubbo文檔筆記
配置覆蓋關系
以 timeout 為例,顯示了配置的查找順序,其它 retries, loadbalance, actives 等類似:
- 方法級優先,接口級次之,全局配置再次之。
- 如果級別一樣,則消費方優先,提供方次之。
其中,服務提供方配置,通過 URL 經由註冊中心傳遞給消費方。
查找次序:
- reference method
<dubbo:reference interface="com.xxx.XxxService">
<dubbo:method name="findXxx" timeout="1000">
</dubbo:reference
- service method
<dubbo:service interface="com.xxx.XxxService">
<dubbo:method name="findXxx" timeout="1000">
</dubbo:service
- reference
<dubbo:reference interface="com.xxx.XxxService" timeout="3000"/>
- service
<dubbo:service interface="com.xxx.XxxService" timeout="4000">
- consumer
<dubbo:consumer timeout="5000"/>
- provider
<dubbo:provider timeout="6000" />
建議由服務提供方設置超時,因為一個方法需要執行多長時間,服務提供方更清楚,如果一個消費方同時引用多個服務,就不需要關心每個服務的超時設置。
屬性配置:
Dubbo 將自動加載 classpath 根目錄下的 dubbo.properties,可以通過JVM啟動參數 -Ddubbo.properties.file=xxx.properties 改變缺省配置位置。
映射規則:
將 XML 配置的標簽名,加屬性名,用點分隔,多個屬性拆成多行
比如: dubbo.application.name=foo 等價於
比如: dubbo.registry.address=10.20.153.10:9090 等價於
如果 XML 有多行同名標簽配置,可用 id 號區分,如果沒有 id 號將對所有同名標簽生效
比如: dubbo.protocol.rmi.port=1234 等價於
比如: dubbo.registry.china.address=10.20.153.10:9090 等價於
覆蓋策略
- -D
java
? -Ddubbo.protocol.port=20880
- XML
dubbo.xml
?
- dubbo.properties
dubbo.properties
? dubbo.protocal.port=20880
JVM 啟動 -D 參數優先,這樣可以使用戶在部署和啟動時進行參數重寫,比如在啟動時需改變協議的端口。
XML 次之,如果在 XML 中有配置,則 dubbo.properties 中的相應配置項無效。
Properties 最後,相當於缺省值,只有 XML 沒有配置時,dubbo.properties 的相應配置項才會生效,通常用於共享公共配置,比如應用名。
API配置
服務提供者
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();
消費者
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(); // 註意:此代理對象內部封裝了所有通訊細節,對象較重,
集群容錯模式
重試次數配置:
<dubbo:service retries="2" />
<dubbo:reference retries="2" />
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
Failfast Cluster
快速失敗,只發起一次調用,失敗立即報錯。通常用於非冪等性的寫操作,比如新增記錄。
Failsafe Cluster
失敗安全,出現異常時,直接忽略。通常用於寫入審計日誌等操作。
Failback Cluster
失敗自動恢復,後臺記錄失敗請求,定時重發。通常用於消息通知操作。
Forking Cluster
並行調用多個服務器,只要一個成功即返回。通常用於實時性要求較高的讀操作,但需要浪費更多服務資源。可通過 forks="2" 來設置最大並行數。
Broadcast Cluster
廣播調用所有提供者,逐個調用,任意一臺報錯則報錯 。通常用於通知所有提供者更新緩存或日誌等本地資源信息。
按照以下示例在服務提供方和消費方配置集群模式
<dubbo:service cluster="failsafe" />
or
<dubbo:reference cluster="failsafe" />
負載均衡策略
random LoadBalance
隨機,按權重設置隨機概率。
RoundRobin LoadBalance
輪循,按公約後的權重設置輪循比率。
存在慢的提供者累積請求的問題,比如:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,久而久之,所有請求都卡在調到第二臺上。
LeastActive LoadBalance
最少活躍調用數,相同活躍數的隨機,活躍數指調用前後計數差。
使慢的提供者收到更少請求,因為越慢的提供者的調用前後計數差會越大。
ConsistentHash LoadBalance
一致性 Hash,相同參數的請求總是發到同一提供者。
當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動。
配置
服務端服務級別
<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>
直連提供者
忽略註冊中心的提供者列表,A 接口配置點對點,不影響 B 接口從註冊中心獲取列表。
- JVM Arugment
java -Dcom.xxx.XxxService=dubbo://10.20.153.10:20880
- Mapping File
${user.home}/dubbo-resolve.properties
? com.xxx.XxxService=dubbo://10.20.153.10:20880
- Reference Config
通過XML配置
通過 -D 參數指定
java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
通過文件映射
java -Ddubbo.resolve.file=xxx.properties
xxx.properties:
? com.alibaba.xxx.XxxService=dubbo://localhost:20890
只訂閱
為方便開發測試,經常會在線下共用一個所有服務可用的註冊中心,這時,如果一個正在開發中的服務提供者註冊,可能會影響消費者不能正常運行。
可以讓服務提供者開發方,只訂閱服務(開發的服務可能依賴其它服務),而不註冊正在開發的服務,通過直連測試正在開發的服務。
禁用註冊配置
<dubbo:registry address="10.20.153.10:9090" register="false" />
or
<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" />
or
<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" />
<dubbo:registry id="qdRegistry" address="10.20.141.150:9090?subscribe=false" />
多協議
不同服務不同協議
不同服務在性能上適用不同協議進行傳輸,比如大數據用短連接協議,小數據大並發用長連接協議
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springfr
amework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp:
//code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" passwo
rd="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>
使用多個協議暴露服務
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springfr
amework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp:
//code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" passwo
rd="hello1234" />
<!-- 多協議配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="8080" />
<!-- 使用多個協議暴露服務 -->
<dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" ve
rsion="1.0.0" protocol="dubbo,hessian" />
</beans>
多註冊中心
比如:中文站有些服務來不及在青島部署,只在杭州部署,而青島的其它應用需要引用此服務,就可以將服務同時註冊到兩個註冊中心。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springfr
amework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp:
//code.alibabatech.com/schema/dubbo/dubbo.xsd">
<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>
不同服務使用不同註冊中心
比如:CRM 有些服務是專門為國際站設計的,有些服務是專門為中文站設計的。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springfr
amework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp:
//code.alibabatech.com/schema/dubbo/dubbo.xsd">
<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>
多註冊中心引用
比如:CRM 需同時調用中文站和國際站的 PC2 服務,PC2 在中文站和國際站均有部署,接口及版本號都一樣,但連的數據庫不一樣。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springfr
amework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp:
//code.alibabatech.com/schema/dubbo/dubbo.xsd">
<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.HelloServ
ice" version="1.0.0" registry="chinaRegistry" />
<!-- 引用國際站站服務 -->
<dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloServi
ce" version="1.0.0" registry="intlRegistry" />
</beans>
多版本
當一個接口實現,出現不兼容升級時,可以用版本號過渡,版本號不同的服務相互間不引用。
可以按照以下的步驟進行版本遷移:
\1. 在低壓力時間段,先升級一半提供者為新版本
\2. 再將所有消費者升級為新版本
\3. 然後將剩下的一半提供者升級為新版本
老版本服務提供者配置:
新版本服務提供者配置:
老版本服務消費者配置:
新版本服務消費者配置:
如果不需要區分版本,可以按照以下的方式配置 :
結果緩存
結果緩存 ,用於加速熱門數據的訪問速度,Dubbo 提供聲明式緩存,以減少用戶加緩存的工作量 。
- lru 基於最近最少使用原則刪除多余緩存,保持最熱的數據被緩存。
- threadlocal 當前線程緩存,比如一個頁面渲染,用到很多 portal,每個 portal 都要去查用戶信息,通過線程緩存,可以減少這種多余訪問。
- jcache 與 JSR107 集成,可以橋接各種緩存實現。
<dubbo:reference interface="com.foo.BarService" cache="lru" />
or
<dubbo:reference interface="com.foo.BarService">
<dubbo:method name="findBar" cache="lru" />
</dubbo:reference>
異步調用
基於 NIO 的非阻塞實現並行調用,客戶端不需要啟動多線程即可完成並行調用多個遠程服務,相對多線程開銷較小。
在 consumer.xml 中配置:
<dubbo:reference id="fooService" interface="com.alibaba.foo.FooService">
<dubbo:method name="findFoo" async="true" />
</dubbo:reference>
<dubbo:reference id="barService" interface="com.alibaba.bar.BarService">
<dubbo:method name="findBar" async="true" />
</dubbo:reference>
調用代碼:
// 此調用會立即返回null
fooService.findFoo(fooId);
// 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future
Future<Foo> fooFuture = RpcContext.getContext().getFuture();
// 此調用會立即返回null
barService.findBar(barId);
// 拿到調用的Future引用,當結果返回後,會被通知和設置到此Future
Future<Bar> barFuture = RpcContext.getContext().getFuture();
// 此時findFoo和findBar的請求同時在執行,客戶端不需要啟動多線程來支持並行,而是借助NIO的非阻塞完成
// 如果foo已返回,直接拿到返回值,否則線程wait住,等待foo返回後,線程會被notify喚醒
Foo foo = fooFuture.get();
// 同理等待bar返回
Bar bar = barFuture.get();
// 如果foo需要5秒返回,bar需要6秒返回,實際只需等6秒,即可獲取到foo和bar,進行接下來的處理。
你也可以設置是否等待消息發出:
sent="true" 等待消息發出,消息發送失敗將拋出異常。
sent="false" 不等待消息發出,將消息放入 IO 隊列,即刻返回。
如果你只是想異步,完全忽略返回值,可以配置 return="false" ,以減少 Future 對象的創建和管理成本:
延遲暴露
如果你的服務需要預熱時間,比如初始化緩存,等待相關資源就位等,可以使用 delay 進行延遲暴露。
延遲5秒暴露服務
延遲到spring初始化完成後,在暴露服務
並發控制
限制 com.foo.BarService 的每個方法,服務器端並發執行(或占用線程池線程數)不能超過10 個:
限制 com.foo.BarService 的 sayHello 方法,服務器端並發執行(或占用線程池線程數)不能超過 10 個:
<dubbo:service interface="com.foo.BarService">
<dubbo:method name="sayHello" executes="10" />
</dubbo:service>
限制 com.foo.BarService 的每個方法,每客戶端並發執行(或占用連接的請求數)不能超過10 個:
<dubbo:service interface="com.foo.BarService" actives="10" />
或
<dubbo:reference interface="com.foo.BarService" actives="10" />
限制 com.foo.BarService 的 sayHello 方法,每客戶端並發執行(或占用連接的請求數)不能超過 10 個:
<dubbo:service interface="com.foo.BarService">
<dubbo:method name="sayHello" actives="10" />
</dubbo:service>
or
<dubbo:reference interface="com.foo.BarService">
<dubbo:method name="sayHello" actives="10" />
</dubbo:service>
Load Balance 均衡
配置服務的客戶端的 loadbalance 屬性為 leastactive ,此 Loadbalance 會調用並發數最小的 Provider(Consumer端並發數)。
<dubbo:reference interface="com.foo.BarService" loadbalance="leastactive" />
or
<dubbo:service interface="com.foo.BarService" loadbalance="leastactive" />
粘滯連接
粘滯連接用於有狀態服務,盡可能讓客戶端總是向同一提供者發起調用,除非該提供者掛了,再連另一臺。
粘滯連接將自動開啟延遲連接,以減少長連接數。
Multicast註冊中心
Multicast 註冊中心不需要啟動任何中心節點,只要廣播地址一樣,就可以互相發現。
\1. 提供方啟動時廣播自己的地址
\2. 消費方啟動時廣播訂閱請求
\3. 提供方收到訂閱請求時,單播自己的地址給訂閱者,如果設置了 unicast=false ,則廣播給訂閱者
\4. 消費方收到提供方地址時,連接該地址進行 RPC 調用
組播受網絡結構限制,只適合小規模應用或開發階段使用。組播地址段: 224.0.0.0 - 239.255.255.255
配置
<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 註冊中心
支持以下功能:
- 當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者信息
- 當註冊中心重啟時,能自動恢復註冊數據,以及訂閱請求
- 當會話過期時,能自動恢復註冊數據,以及訂閱請求當設置
- 可通過
- 可通過
- 支持 * 號通配符
使用 zkclient 客戶端
配置
<dubbo:registry ... client="zkclient" />
or
dubbo.registry.client=zkclient
or
zookeeper://10.20.153.10:2181?client=zkclient
使用 curator 客戶端
配置
<dubbo:registry ... client="curator" />
or
dubbo.registry.client=curator
or
zookeeper://10.20.153.10:2181?client=curator
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.2 0.153.12:2181" />
同一Zookeeper,分成多組註冊中心:
<dubbo:registry id="chinaRegistry" protocol="zookeeper" address="10.20.153.10:2181" gr oup="china" />
<dubbo:registry id="intlRegistry" protocol="zookeeper" address="10.20.153.10:2181" gro up="intl" />
推薦用法
在Provider 上盡量多配置 Consumer 端屬性原因如下:
- 作服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等
- 在 Provider 配置後,Consumer 不配置則會使用 Provider 的配置值,即 Provider 配置可以作為 Consumer 的缺省值 。否則,Consumer 會使用 Consumer 端的全局設置,這對於 Provider 不可控的,並且往往是不合理的
Provider 上盡量多配置 Consumer 端的屬性,讓 Provider 實現者一開始就思考 Provider 服務特點、服務質量的問題。
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="hel loService" timeout="300" retry="2" loadbalance="random" actives="0" />
<dubbo:service interface="com.alibaba.hello.api.WorldService" version="1.0.0" ref="hel loService" timeout="300" retry="2" loadbalance="random" actives="0" >
<dubbo:method name="findAllPerson" timeout="10000" retries="9" loadbalance="leasta ctive" actives="5" />
<dubbo:service/>
dubbo文檔筆記