SpringBoot | 第二十九章:Dubbo的整合和使用
前言
今年年初時,阿里巴巴開源的高效能服務框架
dubbo
又開始了新一輪的更新,還加入了Apache孵化器
。原先專案使用了spring cloud
之後,已經比較少用dubbo
。目前又抽調回原來的行業應用部門,可能還會使用dubbo
進行服務呼叫。趁著編寫教材的機會來進行學習下。而且目前Dubbo
也出了springboot
的starter
專案了,藉著SpringBoot
的東風,整合起來很方便,基本上就一個依賴包引入的問題了。廢話不多說,開始吧~
一點知識
對於沒有接觸過Dubbo
的同學,可以先了解下相關知識。
Dubbo簡介
Dubbo 是阿里巴巴公司一個開源的高效能服務框架,致力於提供高效能和透明化的 RPC 遠端服務呼叫方案,以及 SOA 服務治理方案,使得應用可通過高效能 RPC 實現服務的輸出、輸入功能和 Spring 框架無縫整合。Dubbo 包含遠端通訊、叢集容錯和自動發現三個核心部分。
它提供透明化的遠端方法呼叫,實現像呼叫本地方法一樣呼叫遠端方法,只需簡單配置,沒有任何 API 侵入。同時它具備軟負載均衡及容錯機制,可在內網替代 F5 等硬體負載均衡器,降低成本,減少單點。它可以實現服務自動註冊與發現,不再需要寫死服務提供方地址,註冊中心基於介面名查詢服務提供者的 IP 地址,並且能夠平滑新增或刪除服務提供者。
2011 年末,阿里巴巴在 GitHub 上開源了基於 Java 的分散式服務治理框架 Dubbo,之後它成為了國內該類開源專案的佼佼者,許多開發者對其表示青睞。同時,先後有不少公司在實踐中基於 Dubbo 進行分散式系統架構。目前在 GitHub 上,它的 fork、star 數均已破萬。
Dubbo核心功能:
- 遠端通訊,提供對多種基於長連線的 NIO 框架抽象封裝,包括多種執行緒模型,序列化,以及“請求-響應”模式的資訊交換方式。
- 叢集容錯,提供基於介面方法的透明遠端過程呼叫,包括多協議支援,以及軟負載均衡,失敗容錯,地址路由,動態配置等叢集支援。
- 自動發現,基於註冊中心目錄服務,使服務消費方能動態的查詢服務提供方,使地址透明,使服務提供方可以平滑增加或減少機器。
Dubbo架構
- 服務提供者 - 啟動時在指定埠上暴露服務,並將服務地址和埠註冊到註冊中心上
- 服務消費者 - 啟動時向註冊中心訂閱自己感興趣的服務,以便獲得服務提供方的地址列表
- 註冊中心 - 負責服務的註冊和發現,負責儲存服務提供方上報的地址資訊,並向服務消費方推送
- 監控中心 - 負責收集服務提供方和消費方的執行狀態,比如服務呼叫次數、延遲等,用於監控
- 執行容器 - 負責服務提供方的初始化、載入以及執行的生命週期管理
部署階段
- 服務提供者在指定埠暴露服務,並向註冊中心註冊服務資訊。
- 服務消費者向註冊中心發起服務地址列表的訂閱。
執行階段
- 註冊中心向服務消費者推送地址列表資訊。
- 服務消費者收到地址列表後,從其中選取一個向目標服務發起呼叫。
- 呼叫過程服務消費者和服務提供者的執行狀態上報給監控中心。
呼叫關係說明
- 服務容器負責啟動,載入,執行服務提供者。
- 服務提供者在啟動時,向註冊中心註冊自己提供的服務。
- 服務消費者在啟動時,向註冊中心訂閱自己所需的服務。
- 註冊中心返回服務提供者地址列表給消費者,如果有變更,註冊中心將基於長連線推送變更資料給消費者。
- 服務消費者,從提供者地址列表中,基於軟負載均衡演算法,選一臺提供者進行呼叫,如果呼叫失敗,再選另一臺呼叫。
- 服務消費者和提供者,在記憶體中累計呼叫次數和呼叫時間,定時每分鐘傳送一次統計資料到監控中心。
Dubbo特點
Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。
連通性
- 註冊中心負責服務地址的註冊與查詢,相當於目錄服務,服務提供者和消費者只在啟動時與註冊中心互動,註冊中心不轉發請求,壓力較小
- 監控中心負責統計各服務呼叫次數,呼叫時間等,統計先在記憶體彙總後每分鐘一次傳送到監控中心伺服器,並以報表展示
- 服務提供者向註冊中心註冊其提供的服務,並彙報呼叫時間到監控中心,此時間不包含網路開銷
- 服務消費者向註冊中心獲取服務提供者地址列表,並根據負載演算法直接呼叫提供者,同時彙報呼叫時間到監控中心,此時間包含網路開銷
- 註冊中心,服務提供者,服務消費者三者之間均為長連線,監控中心除外
- 註冊中心通過長連線感知服務提供者的存在,服務提供者宕機,註冊中心將立即推送事件通知消費者
- 註冊中心和監控中心全部宕機,不影響已執行的提供者和消費者,消費者在本地快取了提供者列表
- 註冊中心和監控中心都是可選的,服務消費者可以直連服務提供者
健壯性
- 監控中心宕掉不影響使用,只是丟失部分取樣資料
- 資料庫宕掉後,註冊中心仍能通過快取提供服務列表查詢,但不能註冊新服務
- 註冊中心對等叢集,任意一臺宕掉後,將自動切換到另一臺
- 註冊中心全部宕掉後,服務提供者和服務消費者仍能通過本地快取通訊
- 服務提供者無狀態,任意一臺宕掉後,不影響使用
- 服務提供者全部宕掉後,服務消費者應用將無法使用,並無限次重連等待服務提供者恢復
伸縮性
- 註冊中心為對等叢集,可動態增加機器部署例項,所有客戶端將自動發現新的註冊中心
- 服務提供者無狀態,可動態增加機器部署例項,註冊中心將推送新的服務提供者資訊給消費者
升級性
當服務叢集規模進一步擴大,帶動IT治理結構進一步升級,需要實現動態部署,進行流動計算,現有分散式服務架構不會帶來阻力。下圖是未來可能的一種架構:
節點角色說明
節點 | 角色說明 |
---|---|
Deployer |
自動部署服務的本地代理 |
Repository |
倉庫用於儲存服務應用釋出包 |
Scheduler |
排程中心基於訪問壓力自動增減服務提供者 |
Admin |
統一管理控制檯 |
Registry |
服務註冊與發現的註冊中心 |
Monitor |
統計服務的呼叫次數和呼叫時間的監控中心 |
Dubbo整合和使用
基於官方的
incubator-dubbo-spring-boot-project
專案,在SpringBoot
中整合起來很簡單。
注意:由於本系列還是使用1.5.x
版本進行講解,所以使用的版本為0.1.x
。若使用SpringBoot2.x
的同學,可以使用0.2.x
版本。
這裡為了方便,直接建立了一個介面工程,spring-boot-dubbo-api
。
IHelloService.java
/**
* 定義一個介面
* @author oKong
*
*/
public interface IHelloService {
String hello(String name);
}
服務提供者
建立一個spring-boot-dubbo-provider
工程。
0.引入pom依賴。
<!-- 引入api -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-boot-dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo依賴 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.1.1</version>
</dependency>
<!-- 引入redis作為註冊中心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
注意:這裡直接選用了redis
作為註冊中心使用。預設是zookeeper
。
1.編寫介面實現類。
HelloServiceImpl.java
/**
* 定義一個服務實現類
* @author oKong
*
*/
// 這裡注意 此類@service是dubbo的
@Service(
version = "${demo.service.version}", //版本
application = "${dubbo.application.id}", //應用ID
protocol = "${dubbo.protocol.id}", //協議id
registry = "${dubbo.registry.id}")//註冊中心id
@Slf4j
public class HelloServiceImpl implements IHelloService {
@Override
public String hello(String name) {
log.info("dubbo提供者,引數name:{}", name);
return "hello " + name + ",this is a dubbo provider!";
}
}
說明下:這裡的@Service
是包路徑com.alibaba.dubbo.config.annotation.Service
下的註解類,其指定了介面版本、協議id、註冊中心id等基本資訊。這裡注意還是版本號有用,因為會一個介面多版本共存問題,所以一般上都會設定版本資訊的。
2.設定配置檔案資訊,新增dubbo
相關資訊,比如註冊中心型別,地址等。
# 應用名稱 便於識別
dubbo.application.id=spring-boot-dubbo-provider
dubbo.application.name=spring-boot-dubbo-provider
server.port=8686
# 設定版本
demo.service.version=1.0.0
#協議 可選dubbo redis、http、thrift等
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
#設定掃描路徑 被註解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.provider.service
# 註冊中心配置
dubbo.registry.id=okong-registry
#註冊中心型別 這裡使用redis作為註冊中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設定使用者名稱密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設定redis引數
# 連線池中的最大空閒連線
dubbo.registry.parameters.max.idle=8
# 連線池最大連線數(使用負值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連線池中的最大空閒連線
dubbo.registry.parameters.max-idle=8
# 連線池中的最小空閒連線
dubbo.registry.parameters.min-idle=0
注意:這裡為了方便,直接使用了Redis
作為了註冊中心。對於redis
連線相關配置引數,可以通過dubbo.registry.parameters.xxx
的形式來進行設定,由於parameters
是個Map
物件,所以新增的key是不會進行大小寫轉換的,填寫了什麼就是什麼。具體的registry
配置物件,可以檢視com.alibaba.dubbo.config.RegistryConfig
類。而對於redis
相關引數配置,可以檢視com.alibaba.dubbo.registry.redis.RedisRegistry
類。
其他的註冊中心,也是類似的,大家可在包com.alibaba.dubbo.registry
找到都要的註冊中心配置類。
3.啟動類編寫。
DubboProviderApplication.java
/**
* dubbo-提供者
* @author oKong
*
*/
@SpringBootApplication
@Slf4j
public class DubboProviderApplication {
public static void main(String[] args) throws Exception {
//由於dubbo提供者只是單純提供服務的 可以為一個非web環境
new SpringApplicationBuilder(DubboProviderApplication.class).web(false).run(args);
log.info("spring-boot-dubbo-provider啟動!");
}
}
4.啟動應用,可以訪問下redis
服務,可以看見已經有服務列表資訊了。
服務消費者
建立spring-boot-dubbo-consumer
工程。
0.引入pom依賴
<!-- 引入api -->
<dependency>
<groupId>cn.lqdev.learning</groupId>
<artifactId>spring-boot-dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo依賴 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.1.1</version>
</dependency>
<!-- 引入redis作為註冊中心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.配置檔案添加註冊中心及服務版本相關資訊
# 應用名稱 便於識別
dubbo.application.id=spring-boot-dubbo-consumer
dubbo.application.name=spring-boot-dubbo-consumer
server.port=9696
#設定掃描路徑 被註解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.consumer
# 註冊中心配置
dubbo.registry.id=okong-registry
#註冊中心型別 這裡使用redis作為註冊中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設定使用者名稱密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設定redis引數
# 連線池中的最大空閒連線
dubbo.registry.parameters.max.idle=8
# 連線池最大連線數(使用負值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連線池中的最大空閒連線
dubbo.registry.parameters.max-idle=8
# 連線池中的最小空閒連線
dubbo.registry.parameters.min-idle=0
2.啟動類編寫
DubboConsumerApplication.java
/**
* dubbo-消費者例項
* @author oKong
*
*/
@SpringBootApplication
@Slf4j
public class DubboConsumerApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(DubboConsumerApplication.class, args);
log.info("spring-boot-dubbo-consumer啟動!");
}
}
3.編寫一個rest
api介面服務,進行服務呼叫。
/**
* 呼叫例項
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController {
/**
* 申明為一個reference,其實就是設定一個bean類了,
* 將原來xml配置替換成註解而已
* <dubbo:reference id=“xxxService” interface=“com.xxx.XxxService” />
*/
@Reference(version = "1.0.0")
IHelloService helloService;
@GetMapping("/hello")
public String hello(String name) {
log.info("呼叫提供者服務,引數name:{}", name);
return helloService.hello(name);
}
}
4.啟動應用,訪問:http://127.0.0.1:9696/hello?name=oKong ,可以看見服務呼叫成功了。
監控後臺
官方監控預設支援了zookeeper。而且官方文件也說了,對於
redis
橋接實現只為開源版本提供,其可靠性依賴於 Redis 本身的可靠性。建議大家還是使用zookeeper
吧,redis
還是作為快取使用吧。
監控臺地址:https://github.com/apache/incubator-dubbo-ops 大家可自行安裝說明進行編譯執行下。
新的監控介面:
加入了Apache孵化器
後,介面都是英文的了。。。還是原來的看的舒服呀!
參考資料
總結
本章節主要介紹了
dubbo
的整合和簡單的使用。具體其他的使用其實和原先是一樣的,並沒有什麼區別。建議大家還是去看看官方文件,目前改版後內容豐富多了,乾貨很多,建議還是去看看。這下終於是中文版的了,看的不頭疼了,⊙﹏⊙‖∣
最後
目前網際網路上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支援。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 微信公眾號:
lqdevOps