概要:
- Dubbo 快速入門
- Dubbo 常規配置說明
一、Dubbo 快速入門
Dubbo核心功能解釋
dubbo 阿里開源的一個SOA服務治理框架,從目前來看把它稱作是一個RPC遠程調用框架更爲貼切。單從RPC框架來說,功能較完善,支持多種傳輸和序列化方案。所以想必大家已經知道他的核心功能了:就是遠程調用。
快速演示Dubbo的遠程調用
實現步驟
- 創建服務端項目
- 引入dubbo 依賴
-
- 編寫服務端代碼
- 創建客戶端項目
- 引入dubbo 依賴
-
- 編寫客戶端調用代碼
dubbo 引入:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
dubbo 默認依懶:
客戶端代碼:
static String remoteUrl = "dubbo://127.0.0.1:12345/tuling.dubbo.server.UserService";
// 構建遠程服務對象
public UserService buildRemoteService(String remoteUrl) {
ApplicationConfig application = new ApplicationConfig();
application.setName("young-app");
ReferenceConfig<UserService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(application);
referenceConfig.setInterface(UserService.class);
referenceConfig.setUrl(remoteUrl);
UserService userService = referenceConfig.get();
return userService;
}
服務端代碼:
public void openServer(int port) {
ApplicationConfig config = new ApplicationConfig();
config.setName("simple-app");
ProtocolConfig protocolConfig=new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(port);
protocolConfig.setThreads(20);
ServiceConfig<UserService> serviceConfig=new ServiceConfig();
serviceConfig.setApplication(config);
serviceConfig.setProtocol(protocolConfig);
serviceConfig.setRegistry(new RegistryConfig(RegistryConfig.NO_AVAILABLE));
serviceConfig.setInterface(UserService.class);
serviceConfig.setRef(new UserServiceImpl());
serviceConfig.export();
}
基於Dubbo實現服務集羣:
在上一個例子中如多個服務的集羣?即當有多個服務同時提供的時候,客戶端該調用哪個?以什麼方式進行調用以實現負載均衡?
一個簡單的辦法是將多個服務的URL同時設置到客戶端並初始化對應的服務實例,然後以輪詢的方式進行調用。
但如果訪問增大,需要擴容服務器數量,那麼就必須增加配置重啓客戶端實例。顯然這不是我們願意看到的。Dubbo引入了服務註冊中的概念,可以解決動態擴容的問題。
演示基於註冊中心實現服集羣:
- 修改服務端代碼,添加multicast 註冊中心。
- 修改客戶端代碼,添加multicast 註冊中心。
- 觀察 多個服務時,客戶端如何調用。
- 觀察 動態增減服務,客戶端的調用。
# 服務端連接註冊中心
serviceConfig.setRegistry(new RegistryConfig("multicast://224.1.1.1:2222"));
# 客戶端連接註冊中心
referenceConfig.setRegistry(new RegistryConfig("multicast://224.1.1.1:2222"));
#查看 基於UDP 佔用的2222 端口
netstat -ano|findstr 2222
基於spring IOC維護Dubbo 實例
在前面兩個例子中 出現了,ApplicationConfig、ReferenceConfig、RegistryConfig、com.alibaba.dubbo.config.ServiceConfig等實例 ,很顯然不需要每次調用的時候都去創建該實例那就需要一個IOC 容器去管理這些實例,spring 是一個很好的選擇。
提供者配置----------------------------------
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方應用信息,用於計算依賴關係 -->
<dubbo:application name="simple-app" />
<!-- 使用multicast廣播註冊中心暴露服務地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- 用dubbo協議在20880端口暴露服務 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 聲明需要暴露的服務接口 -->
<dubbo:service interface="tuling.dubbo.server.UserService" ref="userService" />
<!-- 和本地bean一樣實現服務 -->
<bean id="userService" class="tuling.dubbo.server.impl.UserServiceImpl" />
</beans>
提供者服務暴露代碼:
ApplicationContext context = new ClassPathXmlApplicationContext("/spring-provide.xml");
((ClassPathXmlApplicationContext) context).start();
System.in.read();
消費者配置---------------------------------------
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="young-app"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:reference id="userService" interface="tuling.dubbo.server.UserService"/>
</beans>
消費者調用代碼:
ApplicationContext context = new ClassPathXmlApplicationContext("/spring-consumer.xml");
UserService userService = context.getBean(UserService.class);
UserVo u = userService.getUser(1111);
System.out.println(u);
二、Dubbo常規配置說明
Dubbo配置的整體說明:
標籤 |
用途 |
解釋 |
<dubbo:application/> |
公共 |
用於配置當前應用信息,不管該應用是提供者還是消費者 |
<dubbo:registry/> |
公共 |
用於配置連接註冊中心相關信息 |
<dubbo:protocol/> |
服務 |
用於配置提供服務的協議信息,協議由提供方指定,消費方被動接受 |
<dubbo:service/> |
服務 |
用於暴露一個服務,定義服務的元信息,一個服務可以用多個協議暴露,一個服務也可以註冊到多個註冊中心 |
<dubbo:provider/> |
服務 |
當 ProtocolConfig 和 ServiceConfig 某屬性沒有配置時,採用此缺省值,可選 |
<dubbo:consumer/> |
引用 |
當 ReferenceConfig 某屬性沒有配置時,採用此缺省值,可選 |
<dubbo:reference/> |
引用 |
用於創建一個遠程服務代理,一個引用可以指向多個註冊中心 |
<dubbo:method/> |
公共 |
用於 ServiceConfig 和 ReferenceConfig 指定方法級的配置信息 |
<dubbo:argument/> |
公共 |
用於指定方法參數配置 |
配置關係圖:
配置分類
所有配置項分爲三大類。
- 服務發現:表示該配置項用於服務的註冊與發現,目的是讓消費方找到提供方。
- 服務治理:表示該配置項用於治理服務間的關係,或爲開發測試提供便利條件。
- 性能調優:表示該配置項用於調優性能,不同的選項對性能會產生影響。
dubbo 配置的一些套路:
先來看一個簡單配置
<dubbo:service interface="tuling.dubbo.server.UserService" timeout="2000">
通過字面瞭解 timeout即服務的執行超時時間。但當服務執行真正超時的時候 報的錯跟timeout並沒有半毛錢的關係,其異常堆棧如下:
可以看到錯誤表達的意思是 因爲Channel 關閉導致 無法返回 Response 消息。
出現這情況的原因在於 雖然timeout 配置在服務端去是用在客戶端,其表示的是客戶端調用超時間,而非服務端方法的執行超時。當我們去看客戶端的日誌時候就能看到timeout異常了
類似這種配在服務端用在客戶端的配置還有很多,如retries/riː'traɪ/(重試次數)、async/əˈsɪŋk/(是否異步)、loadbalance(負載均衡)。。。等。
套路一:服務端配置客戶端來使用。
注:其參數傳遞機制是 服務端所有配置都會封裝到URL參數,在通過註冊中心傳遞到客戶端
如果需要暴露多個服務的時候,每個服務都要設置其超時時間,貌似有點繁瑣。Dubbo中可以通過 <dubbo:provider> 來實現服務端缺省配置。它可以同時爲 <dubbo:service> 和 <dubbo:protocol> 兩個標籤提供缺省配置。如:
#相當於每個服務提供者設置了超時時間 和重試次數
<dubbo:provider timeout="2000" retries="2"></dubbo:provider>
同樣客戶端也有缺省配置標籤:<dubbo:consumer>,這些缺省設置可以配置多個 通過 <dubbo:service provider="providerId"> ,如果沒指定就用第一個。
套路二:<dubbo:provider>與<dubbo:service> ,<dubbo:consumer>與<dubbo:reference>傻傻分不清楚
在服務端配置timeout 之後 所有客戶端都會採用該方超時時間,其客戶端可以自定義超時時間嗎?通過 <dubbo:reference timeout="2000"> 可以設定或者在<dubbo:consumer timeout="2000"> 也可以設定 甚至可以設定到方法級別 <dubbo:method name="getUser" timeout="2000"/>。加上服務端的配置,超時總共有6處可以配置。如果6處都配置了不同的值,最後肯定只會有一個超時值生效,其優先級如下:
小提示:通過DefaultFuture的get 方法就可觀測到實際的超時設置。
com.alibaba.dubbo.remoting.exchange.support.DefaultFuture
套路三:同一屬性到處配置,優先級要小心。
一般建議配置示例:
提供端:---------------------------
<dubbo:application name="demo-provider"/>
<dubbo:registry protocol="redis" address="192.168.0.147:6379" check="true"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:provider group="tuling.dubbo.demo"
threadpool="fixed"
threads="500"
timeout="5000"
retries="2"
/>
<dubbo:service interface="com.tuling.teach.service.DemoService"
timeout="5000"
retries="1"
version="3.0.0"
ref="demoService"/>
<bean id="demoService" class="com.tuling.teach.service.DemoServiceImpl"/>
消費端示例:--------------------
<dubbo:application name="demo-consumer"/>
<dubbo:registry protocol="redis" address="192.168.0.147:6379" check="true"/>
<dubbo:consumer timeout="5000" retries="2"
group="tuling.dubbo.demo"
version="1.0.0"/>
<dubbo:reference
timeout="3000" retries="1"
id="demoService"
version="*"
interface="com.tuling.teach.service.DemoService"/>