Dubbo 與 Spring Cloud 完美結(jié)合
1. 概述
可能說起來Dubbo,很多人都不陌生,這畢竟是一款從2012年就開始開源的Java
RPC框架,中間由于各種各樣的原因停止更新4年半的時(shí)間,中間只發(fā)過一個(gè)小版本修了一個(gè)小bug,甚至大家都以為這個(gè)項(xiàng)目已經(jīng)死掉了,竟然又在2017年9月份恢復(fù)了更新,不可謂不神奇。
網(wǎng)絡(luò)上很多人都拿Dubbo和Spring
Cloud做對比,可能在大家的心目中,這兩個(gè)框架是可以畫上等號的吧,后來在網(wǎng)絡(luò)上有一個(gè)非常流行的表格,比較詳細(xì)的對比了 Spring Cloud 和
Dubbo ,表格如下:
Dubbo SpringCloud
服務(wù)注冊中心 Zookeeper Spring Cloud Netfix Eureka
服務(wù)調(diào)用方式 RPC REST API
服務(wù)監(jiān)控 Dubbo-monitor Spring Boot Admin
熔斷器 不完善 Spring Cloud Netflix Hystrix
服務(wù)網(wǎng)關(guān) 無 Spring Cloud Netflix Zuul
分布式配置 無 Spring Cloud Config
服務(wù)跟蹤 無 Spring Cloud Sleuth
數(shù)據(jù)流 無 Spring Cloud Stream
批量任務(wù) 無 Spring Cloud Task
信息總線 無 Spring Cloud Bus
以上列舉了一些核心部件,當(dāng)然這里需要申明一點(diǎn),Dubbo對于上表中總結(jié)為“無”的組件不代表不能實(shí)現(xiàn),而只是Dubbo框架自身不提供,需要另外整合以實(shí)現(xiàn)對應(yīng)的功能,這樣看起來確實(shí)Dubbo更像是Spring
Cloud的一個(gè)子集。
Dubbo 在國內(nèi)擁有著巨大的用戶群,大家希望在使用 Dubbo 的同時(shí)享受 Spring Cloud
的生態(tài),出現(xiàn)各種各樣的整合方案,但是因?yàn)榉?wù)中心的不同,各種整合方案并不是那么自然,直到 Spring Cloud Alibaba 這個(gè)項(xiàng)目出現(xiàn),由官方提供了
Nacos 服務(wù)注冊中心后,才將這個(gè)問題完美的解決。并且提供了 Dubbo 和 Spring Cloud 整合的方案,命名為: Dubbo Spring
Cloud 。
1.2 Dubbo Spring Cloud 概述
Dubbo Spring Cloud 構(gòu)建在原生的 Spring Cloud 之上,其服務(wù)治理方面的能力可認(rèn)為是 Spring Cloud Plus,
不僅完全覆蓋 Spring Cloud 原生特性,而且提供更為穩(wěn)定和成熟的實(shí)現(xiàn),特性比對如下表所示:
功能組件 Spring Cloud Dubbo Spring Cloud
分布式配置(Distributed configuration) Git、Zookeeper、Consul、JDBC Spring Cloud 分布式配置
+ Dubbo 配置中心
服務(wù)注冊與發(fā)現(xiàn)(Service registration and discovery) Eureka、Zookeeper、Consul Spring
Cloud 原生注冊中心 + Dubbo 原生注冊中心
負(fù)載均衡(Load balancing) Ribbon(隨機(jī)、輪詢等算法) Dubbo 內(nèi)建實(shí)現(xiàn)(隨機(jī)、輪詢等算法 + 權(quán)重等特性)
服務(wù)熔斷(Circuit Breakers) Spring Cloud Hystrix Spring Cloud Hystrix + Alibaba
Sentinel 等
服務(wù)調(diào)用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服務(wù)調(diào)用 +
Dubbo @Reference
鏈路跟蹤(Tracing) Spring Cloud Sleuth + Zipkin Zipkin、opentracing 等
以上對比表格摘自Dubbo Spring Cloud官方文檔。
而且Dubbo Spring Cloud 基于 Dubbo Spring Boot 2.7.1 和 Spring Cloud 2.x 開發(fā),無論開發(fā)人員是
Dubbo 用戶還是 Spring Cloud 用戶, 都能輕松地駕馭,并以接近“零”成本的代價(jià)使應(yīng)用向上遷移。Dubbo Spring Cloud
致力于簡化云原生開發(fā)成本,以達(dá)成提高研發(fā)效能以及提升應(yīng)用性能等目的。
1.3 Dubbo Spring Cloud 主要特性
* 面向接口代理的高性能RPC調(diào)用:提供高性能的基于代理的遠(yuǎn)程調(diào)用能力,服務(wù)以接口為粒度,屏蔽了遠(yuǎn)程調(diào)用底層細(xì)節(jié)。
* 智能負(fù)載均衡:內(nèi)置多種負(fù)載均衡策略,智能感知下游節(jié)點(diǎn)健康狀況,顯著減少調(diào)用延遲,提高系統(tǒng)吞吐量。
* 服務(wù)自動(dòng)注冊與發(fā)現(xiàn):支持多種注冊中心服務(wù),服務(wù)實(shí)例上下線實(shí)時(shí)感知。
*
高度可擴(kuò)展能力:遵循微內(nèi)核+插件的設(shè)計(jì)原則,所有核心能力如Protocol、Transport、Serialization被設(shè)計(jì)為擴(kuò)展點(diǎn),平等對待內(nèi)置實(shí)現(xiàn)和第三方實(shí)現(xiàn)。
* 運(yùn)行期流量調(diào)度:內(nèi)置條件、腳本等路由策略,通過配置不同的路由規(guī)則,輕松實(shí)現(xiàn)灰度發(fā)布,同機(jī)房優(yōu)先等功能。
* 可視化的服務(wù)治理與運(yùn)維:提供豐富服務(wù)治理、運(yùn)維工具:隨時(shí)查詢服務(wù)元數(shù)據(jù)、服務(wù)健康狀態(tài)及調(diào)用統(tǒng)計(jì),實(shí)時(shí)下發(fā)路由策略、調(diào)整配置參數(shù)。
1.4 Spring Cloud 為什么需要RPC
在Spring
Cloud構(gòu)建的微服務(wù)系統(tǒng)中,大多數(shù)的開發(fā)者使用都是官方提供的Feign組件來進(jìn)行內(nèi)部服務(wù)通信,這種聲明式的HTTP客戶端使用起來非常的簡潔、方便、優(yōu)雅,但是有一點(diǎn),在使用Feign消費(fèi)服務(wù)的時(shí)候,相比較Dubbo這種RPC框架而言,性能堪憂。
雖說在微服務(wù)架構(gòu)中,會講按照業(yè)務(wù)劃分的微服務(wù)獨(dú)立部署,并且運(yùn)行在各自的進(jìn)程中。微服務(wù)之間的通信更加傾向于使用HTTP這種簡答的通信機(jī)制,大多數(shù)情況都會使用REST
API。這種通信方式非常的簡潔高效,并且和開發(fā)平臺、語言無關(guān),但是通常情況下,HTTP并不會開啟KeepAlive功能,即當(dāng)前連接為短連接,短連接的缺點(diǎn)是每次請求都需要建立TCP連接,這使得其效率變的相當(dāng)?shù)拖隆?br>
對外部提供REST API服務(wù)是一件非常好的事情,但是如果內(nèi)部調(diào)用也是使用HTTP調(diào)用方式,就會顯得顯得性能低下,Spring
Cloud默認(rèn)使用的Feign組件進(jìn)行內(nèi)部服務(wù)調(diào)用就是使用的HTTP協(xié)議進(jìn)行調(diào)用,這時(shí),我們?nèi)绻麅?nèi)部服務(wù)使用RPC調(diào)用,對外使用REST
API,將會是一個(gè)非常不錯(cuò)的選擇,恰巧,Dubbo Spring Cloud給了我們這種選擇的實(shí)現(xiàn)方式。
2. 實(shí)戰(zhàn)
本小結(jié)將會以一個(gè)簡單的入門案例,介紹一下在使用Nacos作為服務(wù)中心,使用Dubbo來實(shí)現(xiàn)服務(wù)提供方和服務(wù)消費(fèi)方的案例。
Nacos的安裝、部署配置和使用已經(jīng)在前面的章節(jié)介紹過了,這里不再贅述,如果還有不清楚的讀者,請參考前面的Nacos系列文章:
《Spring Cloud Alibaba | Nacos服務(wù)中心初探》
<https://www.geekdigging.com/2019/08/31/4006904047/>
《Spring Cloud Alibaba | Nacos服務(wù)注冊與發(fā)現(xiàn)》
<https://www.geekdigging.com/2019/08/31/3763985100/>
《Spring Cloud Alibaba | Nacos集群部署》
<https://www.geekdigging.com/2019/08/31/2293861818/>
《Spring Cloud Alibaba | Nacos配置管理》
<https://www.geekdigging.com/2019/08/31/3656100408/>
2.1 創(chuàng)建父工程 dubbo-spring-cloud-demo
父工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/pom.xml
***
<dependencyManagement> <dependencies> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version> <type>pom</type>
<scope>import</scope> </dependency> <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version> <type>pom</type>
<scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Dubbo
Spring Cloud Starter --> <dependency> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <!-- Spring
Cloud Nacos Service Discovery --> <dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency> <dependency> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <optional>true</optional> </dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
</dependency> </dependencies>
注意:
* 必須包含spring-boot-starter-actuator包,不然啟動(dòng)會報(bào)錯(cuò)。
*
spring-cloud-starter-dubbo包需要注意groupId,根據(jù)具體使用的spring cloud alibaba版本依賴來確定。
* 如果使用孵化版本,使用的groupId為:org.springframework.cloud
* 如果使用畢業(yè)版本,使用的groupId為:com.alibaba.cloud
*
以上引用未指定版本,需顯示的聲明<dependencyManagement>
2.2 創(chuàng)建子工程 dubbo_api
API模塊,存放Dubbo服務(wù)接口和模型定義,非必要,這里創(chuàng)建僅為更好的代碼重用以及接口、模型規(guī)格控制管理。
定義抽象接口HelloService.java:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_api/src/main/java/com/springcloud/dubbo_api/service/HelloService.java
***
public interface HelloService { String hello(String name); }
2.3 創(chuàng)建子工程 dubbo_provider ,Dubbo服務(wù)提供方
工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_provider/pom.xml
***
<!-- API --> <dependency> <groupId>com.springcloud.book</groupId>
<artifactId>ch13_1_dubbo_api</artifactId> <version>${project.version}</version>
</dependency>
此處引入公共API模塊。
實(shí)現(xiàn)Dubbo接口,HelloServiceI.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_provider/src/main/java/com/springcloud/dubbo_provider/service/HelloServiceI.java
***
@Service public class HelloServiceI implements HelloService { @Override public
String hello(String name) { return "Hello " + name; } }
注意:這里的@Service注解并不是來自Spring的org.springframework.stereotype.Service,而是Dubbo的
org.apache.dubbo.config.annotation.Service,千萬不要引用錯(cuò)誤。這里的@Service
注解僅聲明該Java服務(wù)(本地)實(shí)現(xiàn)為Dubbo服務(wù)。
配置文件 application.yml 需要將Java服務(wù)(本地)配置為 Dubbo 服務(wù)(遠(yuǎn)程)如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_provider/src/main/resources/application.yml
***
server: port: 8000 dubbo: scan: base-packages:
com.springcloud.book.ch13_1_dubbo_provider.service protocol: name: dubbo port:
-1 registry: address: spring-cloud://192.168.44.129 spring: application: name:
dubbo-spring-cloud-provider cloud: nacos: discovery: server-addr:
192.168.44.129:8848 main: allow-bean-definition-overriding: true
注意:在暴露Dubbo服務(wù)方面,推薦使用外部化配置的方式,即指定Java服務(wù)實(shí)現(xiàn)類的掃描基準(zhǔn)包。
Dubbo Spring Cloud 繼承了 Dubbo Spring Boot 的外部化配置特性,也可以通過標(biāo)注 @DubboComponentScan
來實(shí)現(xiàn)基準(zhǔn)包掃描。
* dubbo.scan.base-packages:指定 Dubbo 服務(wù)實(shí)現(xiàn)類的掃描基準(zhǔn)包
* dubbo.protocol:Dubbo服務(wù)暴露的協(xié)議配置,其中子屬性name為協(xié)議名稱,port為協(xié)議端口(-1 表示自增端口,從 20880 開始)
* dubbo.registry:Dubbo 服務(wù)注冊中心配置,其中子屬性address 的值
"spring-cloud://192.168.44.129",說明掛載到 Spring Cloud 注冊中心
* spring.application.name:Spring 應(yīng)用名稱,用于 Spring Cloud 服務(wù)注冊和發(fā)現(xiàn)。該值在 Dubbo
Spring Cloud 加持下被視作dubbo.application.name,因此,無需再顯示地配置dubbo.application.name。
* spring.main.allow-bean-definition-overriding:在 Spring Boot 2.1
以及更高的版本增加該設(shè)定,因?yàn)?Spring Boot 默認(rèn)調(diào)整了 Bean 定義覆蓋行為。
* spring.cloud.nacos.discovery:Nacos 服務(wù)發(fā)現(xiàn)與注冊配置,其中子屬性 server-addr 指定 Nacos
服務(wù)器主機(jī)和端口。
創(chuàng)建應(yīng)用主類Ch131DubboProviderApplication.java:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_provider/src/main/java/com/springcloud/dubbo_provider/DubboProviderApplication.java
***
@SpringBootApplication @EnableDiscoveryClient public class
DubboProviderApplication { public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args); } }
2.4 創(chuàng)建子工程 dubbo_consumer ,服務(wù)調(diào)用方:
工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_consumer/pom.xml
***
<!-- API --> <dependency> <groupId>com.springcloud.book</groupId>
<artifactId>ch13_1_dubbo_api</artifactId> <version>${project.version}</version>
</dependency>
工程配置application.yml如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_consumer/src/main/resources/application.yml
***
server: port: 8080 dubbo: protocol: name: dubbo port: -1 registry: address:
spring-cloud://192.168.44.129 cloud: subscribed-services:
dubbo-spring-cloud-provider spring: application: name:
dubbo-spring-cloud-consumer cloud: nacos: discovery: server-addr:
192.168.44.129:8848 main: allow-bean-definition-overriding: true
* dubbo.cloud.subscribed-services:表示要訂閱服務(wù)的服務(wù)名,可以配置'*'
,代表訂閱所有服務(wù),不推薦使用。若需訂閱多應(yīng)用,使用 "," 分割。
測試接口HelloController.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_consumer/src/main/java/com/springcloud/dubbo_consumer/controller/HelloController.java
***
@RestController public class HelloController { @Reference private HelloService
helloService; @GetMapping("/hello") public String hello() { return
helloService.hello("Dubbo!"); } }
注意:這里的@Reference注解是org.apache.dubbo.config.annotation.Reference。
啟動(dòng)主類Ch131DubboConsumerApplication.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-demo/dubbo_consumer/src/main/java/com/springcloud/dubbo_consumer/DubboConsumerApplication.java
***
@SpringBootApplication @EnableDiscoveryClient public class
DubboConsumerApplication { public static void main(String[] args) {
SpringApplication.run(DubboConsumerApplication.class, args); } }
2.5 測試
啟動(dòng)子工程 dubbo_provider 和子工程 dubbo_consumer ,啟動(dòng)完成后,我們可以訪問Nacos控制臺的服務(wù)列表上看到兩個(gè)服務(wù),如圖:
我們打開瀏覽器訪問:http://localhost:8080/hello ,可以看到頁面正常顯示Hello Dubbo!,測試成功,如圖:
3. 示例代碼
示例代碼-Github
<https://github.com/meteor1993/SpringCloudLearning/tree/master/Alibaba/dubbo-spring-cloud-demo>
示例代碼-Gitee
<https://gitee.com/inwsy/SpringCloudLearning/tree/master/Alibaba/dubbo-spring-cloud-demo>
4. 參考
Dubbo Spring Cloud 官方文檔
<https://github.com/alibaba/spring-cloud-alibaba/wiki/Dubbo-Spring-Cloud>
熱門工具 換一換