SpringBoot | 第二十九章:Dubbo的集成和使用

原文出處: oKong

前言

在18年年初時(shí),阿里巴巴開源的高性能服務(wù)框架dubbo又開始了新一輪的更新,還加入了Apache孵化器。原先項(xiàng)目使用了spring cloud之后,已經(jīng)比較少用dubbo。目前又抽調(diào)回原來的行業(yè)應(yīng)用部門,可能還會(huì)使用dubbo進(jìn)行服務(wù)調(diào)用。趁著編寫教材的機(jī)會(huì)來進(jìn)行學(xué)習(xí)下。而且目前Dubbo也出了springbootstarter項(xiàng)目了,借著SpringBoot的東風(fēng),集成起來很方便,基本上就一個(gè)依賴包引入的問題了。廢話不多說,開始吧~

一點(diǎn)知識(shí)

對(duì)于沒有接觸過Dubbo的同學(xué),可以先了解下相關(guān)知識(shí)。

Dubbo簡介

Dubbo 是阿里巴巴公司一個(gè)開源的高性能服務(wù)框架,致力于提供高性能和透明化的 RPC 遠(yuǎn)程服務(wù)調(diào)用方案,以及 SOA 服務(wù)治理方案,使得應(yīng)用可通過高性能 RPC 實(shí)現(xiàn)服務(wù)的輸出、輸入功能和 Spring 框架無縫集成。Dubbo 包含遠(yuǎn)程通訊、集群容錯(cuò)和自動(dòng)發(fā)現(xiàn)三個(gè)核心部分。

它提供透明化的遠(yuǎn)程方法調(diào)用,實(shí)現(xiàn)像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法,只需簡單配置,沒有任何 API 侵入。同時(shí)它具備軟負(fù)載均衡及容錯(cuò)機(jī)制,可在內(nèi)網(wǎng)替代 F5 等硬件負(fù)載均衡器,降低成本,減少單點(diǎn)。它可以實(shí)現(xiàn)服務(wù)自動(dòng)注冊(cè)與發(fā)現(xiàn),不再需要寫死服務(wù)提供方地址,注冊(cè)中心基于接口名查詢服務(wù)提供者的 IP 地址,并且能夠平滑添加或刪除服務(wù)提供者。

2011 年末,阿里巴巴在 GitHub 上開源了基于 Java 的分布式服務(wù)治理框架 Dubbo,之后它成為了國內(nèi)該類開源項(xiàng)目的佼佼者,許多開發(fā)者對(duì)其表示青睞。同時(shí),先后有不少公司在實(shí)踐中基于 Dubbo 進(jìn)行分布式系統(tǒng)架構(gòu)。目前在 GitHub 上,它的 fork、star 數(shù)均已破萬。

Dubbo核心功能:

  • 遠(yuǎn)程通訊,提供對(duì)多種基于長連接的 NIO 框架抽象封裝,包括多種線程模型,序列化,以及“請(qǐng)求-響應(yīng)”模式的信息交換方式。
  • 集群容錯(cuò),提供基于接口方法的透明遠(yuǎn)程過程調(diào)用,包括多協(xié)議支持,以及軟負(fù)載均衡,失敗容錯(cuò),地址路由,動(dòng)態(tài)配置等集群支持。
  • 自動(dòng)發(fā)現(xiàn),基于注冊(cè)中心目錄服務(wù),使服務(wù)消費(fèi)方能動(dòng)態(tài)的查找服務(wù)提供方,使地址透明,使服務(wù)提供方可以平滑增加或減少機(jī)器。

Dubbo架構(gòu)

  1. 服務(wù)提供者 - 啟動(dòng)時(shí)在指定端口上暴露服務(wù),并將服務(wù)地址和端口注冊(cè)到注冊(cè)中心上
  2. 服務(wù)消費(fèi)者 - 啟動(dòng)時(shí)向注冊(cè)中心訂閱自己感興趣的服務(wù),以便獲得服務(wù)提供方的地址列表
  3. 注冊(cè)中心 - 負(fù)責(zé)服務(wù)的注冊(cè)和發(fā)現(xiàn),負(fù)責(zé)保存服務(wù)提供方上報(bào)的地址信息,并向服務(wù)消費(fèi)方推送
  4. 監(jiān)控中心 - 負(fù)責(zé)收集服務(wù)提供方和消費(fèi)方的運(yùn)行狀態(tài),比如服務(wù)調(diào)用次數(shù)、延遲等,用于監(jiān)控
  5. 運(yùn)行容器 - 負(fù)責(zé)服務(wù)提供方的初始化、加載以及運(yùn)行的生命周期管理

dubbo-architecture

部署階段

  • 服務(wù)提供者在指定端口暴露服務(wù),并向注冊(cè)中心注冊(cè)服務(wù)信息。
  • 服務(wù)消費(fèi)者向注冊(cè)中心發(fā)起服務(wù)地址列表的訂閱。

運(yùn)行階段

  • 注冊(cè)中心向服務(wù)消費(fèi)者推送地址列表信息。
  • 服務(wù)消費(fèi)者收到地址列表后,從其中選取一個(gè)向目標(biāo)服務(wù)發(fā)起調(diào)用。
  • 調(diào)用過程服務(wù)消費(fèi)者和服務(wù)提供者的運(yùn)行狀態(tài)上報(bào)給監(jiān)控中心。

調(diào)用關(guān)系說明

  1. 服務(wù)容器負(fù)責(zé)啟動(dòng),加載,運(yùn)行服務(wù)提供者。
  2. 服務(wù)提供者在啟動(dòng)時(shí),向注冊(cè)中心注冊(cè)自己提供的服務(wù)。
  3. 服務(wù)消費(fèi)者在啟動(dòng)時(shí),向注冊(cè)中心訂閱自己所需的服務(wù)。
  4. 注冊(cè)中心返回服務(wù)提供者地址列表給消費(fèi)者,如果有變更,注冊(cè)中心將基于長連接推送變更數(shù)據(jù)給消費(fèi)者。
  5. 服務(wù)消費(fèi)者,從提供者地址列表中,基于軟負(fù)載均衡算法,選一臺(tái)提供者進(jìn)行調(diào)用,如果調(diào)用失敗,再選另一臺(tái)調(diào)用。
  6. 服務(wù)消費(fèi)者和提供者,在內(nèi)存中累計(jì)調(diào)用次數(shù)和調(diào)用時(shí)間,定時(shí)每分鐘發(fā)送一次統(tǒng)計(jì)數(shù)據(jù)到監(jiān)控中心。

Dubbo特點(diǎn)

Dubbo 架構(gòu)具有以下幾個(gè)特點(diǎn),分別是連通性、健壯性、伸縮性、以及向未來架構(gòu)的升級(jí)性。

連通性

  • 注冊(cè)中心負(fù)責(zé)服務(wù)地址的注冊(cè)與查找,相當(dāng)于目錄服務(wù),服務(wù)提供者和消費(fèi)者只在啟動(dòng)時(shí)與注冊(cè)中心交互,注冊(cè)中心不轉(zhuǎn)發(fā)請(qǐng)求,壓力較小
  • 監(jiān)控中心負(fù)責(zé)統(tǒng)計(jì)各服務(wù)調(diào)用次數(shù),調(diào)用時(shí)間等,統(tǒng)計(jì)先在內(nèi)存匯總后每分鐘一次發(fā)送到監(jiān)控中心服務(wù)器,并以報(bào)表展示
  • 服務(wù)提供者向注冊(cè)中心注冊(cè)其提供的服務(wù),并匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間不包含網(wǎng)絡(luò)開銷
  • 服務(wù)消費(fèi)者向注冊(cè)中心獲取服務(wù)提供者地址列表,并根據(jù)負(fù)載算法直接調(diào)用提供者,同時(shí)匯報(bào)調(diào)用時(shí)間到監(jiān)控中心,此時(shí)間包含網(wǎng)絡(luò)開銷
  • 注冊(cè)中心,服務(wù)提供者,服務(wù)消費(fèi)者三者之間均為長連接,監(jiān)控中心除外
  • 注冊(cè)中心通過長連接感知服務(wù)提供者的存在,服務(wù)提供者宕機(jī),注冊(cè)中心將立即推送事件通知消費(fèi)者
  • 注冊(cè)中心和監(jiān)控中心全部宕機(jī),不影響已運(yùn)行的提供者和消費(fèi)者,消費(fèi)者在本地緩存了提供者列表
  • 注冊(cè)中心和監(jiān)控中心都是可選的,服務(wù)消費(fèi)者可以直連服務(wù)提供者

健壯性

  • 監(jiān)控中心宕掉不影響使用,只是丟失部分采樣數(shù)據(jù)
  • 數(shù)據(jù)庫宕掉后,注冊(cè)中心仍能通過緩存提供服務(wù)列表查詢,但不能注冊(cè)新服務(wù)
  • 注冊(cè)中心對(duì)等集群,任意一臺(tái)宕掉后,將自動(dòng)切換到另一臺(tái)
  • 注冊(cè)中心全部宕掉后,服務(wù)提供者和服務(wù)消費(fèi)者仍能通過本地緩存通訊
  • 服務(wù)提供者無狀態(tài),任意一臺(tái)宕掉后,不影響使用
  • 服務(wù)提供者全部宕掉后,服務(wù)消費(fèi)者應(yīng)用將無法使用,并無限次重連等待服務(wù)提供者恢復(fù)

伸縮性

  • 注冊(cè)中心為對(duì)等集群,可動(dòng)態(tài)增加機(jī)器部署實(shí)例,所有客戶端將自動(dòng)發(fā)現(xiàn)新的注冊(cè)中心
  • 服務(wù)提供者無狀態(tài),可動(dòng)態(tài)增加機(jī)器部署實(shí)例,注冊(cè)中心將推送新的服務(wù)提供者信息給消費(fèi)者

升級(jí)性

當(dāng)服務(wù)集群規(guī)模進(jìn)一步擴(kuò)大,帶動(dòng)IT治理結(jié)構(gòu)進(jìn)一步升級(jí),需要實(shí)現(xiàn)動(dòng)態(tài)部署,進(jìn)行流動(dòng)計(jì)算,現(xiàn)有分布式服務(wù)架構(gòu)不會(huì)帶來阻力。下圖是未來可能的一種架構(gòu):

dubbo-architecture-future.jpg

節(jié)點(diǎn)角色說明

節(jié)點(diǎn) 角色說明
Deployer 自動(dòng)部署服務(wù)的本地代理
Repository 倉庫用于存儲(chǔ)服務(wù)應(yīng)用發(fā)布包
Scheduler 調(diào)度中心基于訪問壓力自動(dòng)增減服務(wù)提供者
Admin 統(tǒng)一管理控制臺(tái)
Registry 服務(wù)注冊(cè)與發(fā)現(xiàn)的注冊(cè)中心
Monitor 統(tǒng)計(jì)服務(wù)的調(diào)用次數(shù)和調(diào)用時(shí)間的監(jiān)控中心

大家可訪問官網(wǎng)文檔:http://dubbo.apache.org/zh-cn/docs/user/quick-start.html,里面有詳細(xì)說明和使用說明的。這里就不再闡述了。

Dubbo集成和使用

基于官方的incubator-dubbo-spring-boot-project項(xiàng)目,在SpringBoot中集成起來很簡單。

注意:由于本系列還是使用1.5.x版本進(jìn)行講解,所以使用的版本為0.1.x。若使用SpringBoot2.x的同學(xué),可以使用0.2.x版本。

官方說明

這里為了方便,直接創(chuàng)建了一個(gè)接口工程,spring-boot-dubbo-api

IHelloService.java

/**
 * 定義一個(gè)接口
 * @author oKong
 *
 */
public interface IHelloService {

 String hello(String name);

}

服務(wù)提供者

創(chuàng)建一個(gè)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作為注冊(cè)中心 -->
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

注意:這里直接選用了redis作為注冊(cè)中心使用。默認(rèn)是zookeeper。

1.編寫接口實(shí)現(xiàn)類。
HelloServiceImpl.java

/**
 * 定義一個(gè)服務(wù)實(shí)現(xiàn)類
 * @author oKong
 *
 */
// 這里注意 此類@service是dubbo的
@Service(
 version = "${demo.service.version}", //版本
 application = "${dubbo.application.id}", //應(yīng)用ID
 protocol = "${dubbo.protocol.id}", //協(xié)議id
 registry = "${dubbo.registry.id}")//注冊(cè)中心id
@Slf4j
public class HelloServiceImpl implements IHelloService {

 @Override
 public String hello(String name) {
 log.info("dubbo提供者,參數(shù)name:{}", name);
 return "hello " + name + ",this is a dubbo provider!";
 }

}

說明下:這里的@Service是包路徑com.alibaba.dubbo.config.annotation.Service下的注解類,其指定了接口版本、協(xié)議id、注冊(cè)中心id等基本信息。這里注意還是版本號(hào)有用,因?yàn)闀?huì)一個(gè)接口多版本共存問題,所以一般上都會(huì)設(shè)置版本信息的。
2.設(shè)置配置文件信息,添加dubbo相關(guān)信息,比如注冊(cè)中心類型,地址等。

# 應(yīng)用名稱 便于識(shí)別
dubbo.application.id=spring-boot-dubbo-provider
dubbo.application.name=spring-boot-dubbo-provider

server.port=8686

# 設(shè)置版本
demo.service.version=1.0.0

#協(xié)議 可選dubbo redis、http、thrift等
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#設(shè)置掃描路徑 被注解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.provider.service

# 注冊(cè)中心配置
dubbo.registry.id=okong-registry
#注冊(cè)中心類型 這里使用redis作為注冊(cè)中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設(shè)置用戶名密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設(shè)置redis參數(shù)
# 連接池中的最大空閑連接
dubbo.registry.parameters.max.idle=8
# 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連接池中的最大空閑連接
dubbo.registry.parameters.max-idle=8
# 連接池中的最小空閑連接
dubbo.registry.parameters.min-idle=0

注意:這里為了方便,直接使用了Redis作為了注冊(cè)中心。對(duì)于redis連接相關(guān)配置參數(shù),可以通過dubbo.registry.parameters.xxx的形式來進(jìn)行設(shè)置,由于parameters是個(gè)Map對(duì)象,所以添加的key是不會(huì)進(jìn)行大小寫轉(zhuǎn)換的,填寫了什么就是什么。具體的registry配置對(duì)象,可以查看com.alibaba.dubbo.config.RegistryConfig類。而對(duì)于redis相關(guān)參數(shù)配置,可以查看com.alibaba.dubbo.registry.redis.RedisRegistry類。

RedisRegistry

其他的注冊(cè)中心,也是類似的,大家可在包com.alibaba.dubbo.registry找到都要的注冊(cè)中心配置類。

3.啟動(dòng)類編寫。

DubboProviderApplication.java

/**
 * dubbo-提供者
 * @author oKong
 *
 */
@SpringBootApplication
@Slf4j
public class DubboProviderApplication {

 public static void main(String[] args) throws Exception {
 //由于dubbo提供者只是單純提供服務(wù)的 可以為一個(gè)非web環(huán)境
 new SpringApplicationBuilder(DubboProviderApplication.class).web(false).run(args);
 log.info("spring-boot-dubbo-provider啟動(dòng)!");
 }

}

4.啟動(dòng)應(yīng)用,可以訪問下redis服務(wù),可以看見已經(jīng)有服務(wù)列表信息了。

redis

服務(wù)消費(fèi)者

創(chuàng)建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作為注冊(cè)中心 -->
 <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.配置文件添加注冊(cè)中心及服務(wù)版本相關(guān)信息

# 應(yīng)用名稱 便于識(shí)別
dubbo.application.id=spring-boot-dubbo-consumer
dubbo.application.name=spring-boot-dubbo-consumer

server.port=9696

#設(shè)置掃描路徑 被注解@service和@Reference 等
dubbo.scan.basePackages=cn.lqdev.learning.springboot.dubbo.consumer

# 注冊(cè)中心配置
dubbo.registry.id=okong-registry
#注冊(cè)中心類型 這里使用redis作為注冊(cè)中心
# zookeeper://127.0.0.1:2181
dubbo.registry.address=redis://127.0.0.1:6379
# 設(shè)置用戶名密碼 若有的話
#dubbo.registry.username=oKong
#dubbo.registry.password=oKong
# 設(shè)置redis參數(shù)
# 連接池中的最大空閑連接
dubbo.registry.parameters.max.idle=8
# 連接池最大連接數(shù)(使用負(fù)值表示沒有限制)
dubbo.registry.parameters.max-active=8
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒有限制)
dubbo.registry.parameters.max-wait=-1
# 連接池中的最大空閑連接
dubbo.registry.parameters.max-idle=8
# 連接池中的最小空閑連接
dubbo.registry.parameters.min-idle=0

2.啟動(dòng)類編寫

DubboConsumerApplication.java

/**
 * dubbo-消費(fèi)者實(shí)例
 * @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啟動(dòng)!");
 }
}

3.編寫一個(gè)restapi接口服務(wù),進(jìn)行服務(wù)調(diào)用。

/**
 * 調(diào)用實(shí)例
 * @author oKong
 *
 */
@RestController
@Slf4j
public class DemoController {

 /**
 * 申明為一個(gè)reference,其實(shí)就是設(shè)置一個(gè)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("調(diào)用提供者服務(wù),參數(shù)name:{}", name);
 return helloService.hello(name);
 }
}

4.啟動(dòng)應(yīng)用,訪問:http://127.0.0.1:9696/hello?name=oKong ,可以看見服務(wù)調(diào)用成功了。

服務(wù)調(diào)用

監(jiān)控后臺(tái)

官方監(jiān)控默認(rèn)支持了zookeeper。而且官方文檔也說了,對(duì)于redis橋接實(shí)現(xiàn)只為開源版本提供,其可靠性依賴于 Redis 本身的可靠性。建議大家還是使用zookeeper吧,redis還是作為緩存使用吧。

監(jiān)控臺(tái)地址:https://github.com/apache/incubator-dubbo-ops
大家可自行安裝說明進(jìn)行編譯運(yùn)行下。

新的監(jiān)控界面:

[圖片上傳失敗...(image-3c6762-1553334118654)]

加入了Apache孵化器后,界面都是英文的了。。。還是原來的看的舒服呀!

[圖片上傳失敗...(image-6efd65-1553334118654)]

參考資料

  1. http://jm.taobao.org/2018/06/13/%E5%BA%94%E7%94%A8/

  2. http://dubbo.apache.org/zh-cn/docs/user/preface/architecture.html

總結(jié)

本章節(jié)主要介紹了dubbo的集成和簡單的使用。具體其他的使用其實(shí)和原先是一樣的,并沒有什么區(qū)別。建議大家還是去看看官方文檔,目前改版后內(nèi)容豐富多了,干貨很多,建議還是去看看。這下終于是中文版的了,看的不頭疼了,⊙﹏⊙‖∣

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同,請(qǐng)多多包涵了。原創(chuàng)不易,碼字不易,還希望大家多多支持。若文中有所錯(cuò)誤之處,還望提出,謝謝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Dubbo是什么 Dubbo是Alibaba開源的分布式服務(wù)框架,它最大的特點(diǎn)是按照分層的方式來架構(gòu),使用這種方式...
    Coselding閱讀 17,447評(píng)論 3 196
  • 0 準(zhǔn)備 安裝注冊(cè)中心:Zookeeper、Dubbox自帶的dubbo-registry-simple;安裝Du...
    七寸知架構(gòu)閱讀 14,106評(píng)論 0 88
  • 本文將為大家介紹當(dāng)下最流行的服務(wù)治理、微服務(wù)等相關(guān)內(nèi)容,從服務(wù)治理、SOA、微服務(wù)到最新的服務(wù)網(wǎng)格(Service...
    勤奮的碼農(nóng)閱讀 699評(píng)論 0 0
  • 我怎么如此幸運(yùn),一早,昨心里想著一個(gè)朋發(fā)信息說會(huì)經(jīng)過家里會(huì)來相聚。原來,真的會(huì)心想事成。 我怎么會(huì)如此幸運(yùn),花開了...
    李婷_4ec1閱讀 343評(píng)論 0 1
  • 這個(gè)世界上人的思維最自由,天馬行空,不受限制。大課培訓(xùn)時(shí),聽著聽著,眼皮開始打架,昏昏入睡。為提神醒腦,拿起保溫杯...
    364閱讀 212評(píng)論 0 0

友情鏈接更多精彩內(nèi)容