Dubbo 與 Spring Cloud 完美結合
Dubbo 與 Spring Cloud 完美結合
1. 概述
可能說起來Dubbo,很多人都不陌生,這畢竟是一款從2012年就開始開源的Java RPC框架,中間由於各種各樣的原因停止更新4年半的時間,中間只發過一個小版本修了一個小bug,甚至大家都以為這個專案已經死掉了,竟然又在2017年9月份恢復了更新,不可謂不神奇。
網路上很多人都拿Dubbo和Spring Cloud做對比,可能在大家的心目中,這兩個框架是可以畫上等號的吧,後來在網路上有一個非常流行的表格,比較詳細的對比了 Spring Cloud 和 Dubbo ,表格如下:
Dubbo | SpringCloud | |
---|---|---|
服務註冊中心 | Zookeeper | Spring Cloud Netfix Eureka |
服務呼叫方式 | RPC | REST API |
服務監控 | Dubbo-monitor | Spring Boot Admin |
熔斷器 | 不完善 | Spring Cloud Netflix Hystrix |
服務閘道器 | 無 | Spring Cloud Netflix Zuul |
分散式配置 | 無 | Spring Cloud Config |
服務跟蹤 | 無 | Spring Cloud Sleuth |
資料流 | 無 | Spring Cloud Stream |
批量任務 | 無 | Spring Cloud Task |
資訊匯流排 | 無 | Spring Cloud Bus |
以上列舉了一些核心部件,當然這裡需要申明一點,Dubbo對於上表中總結為“無”的元件不代表不能實現,而只是Dubbo框架自身不提供,需要另外整合以實現對應的功能,這樣看起來確實Dubbo更像是Spring Cloud的一個子集。
Dubbo 在國內擁有著巨大的使用者群,大家希望在使用 Dubbo 的同時享受 Spring Cloud 的生態,出現各種各樣的整合方案,但是因為服務中心的不同,各種整合方案並不是那麼自然,直到 Spring Cloud Alibaba 這個專案出現,由官方提供了 Nacos 服務註冊中心後,才將這個問題完美的解決。並且提供了 Dubbo 和 Spring Cloud 整合的方案,命名為: Dubbo Spring Cloud 。
1.2 Dubbo Spring Cloud 概述
Dubbo Spring Cloud 構建在原生的 Spring Cloud 之上,其服務治理方面的能力可認為是 Spring Cloud Plus, 不僅完全覆蓋 Spring Cloud 原生特性,而且提供更為穩定和成熟的實現,特性比對如下表所示:
功能元件 | Spring Cloud | Dubbo Spring Cloud |
---|---|---|
分散式配置(Distributed configuration) | Git、Zookeeper、Consul、JDBC | Spring Cloud 分散式配置 + Dubbo 配置中心 |
服務註冊與發現(Service registration and discovery) | Eureka、Zookeeper、Consul | Spring Cloud 原生註冊中心 + Dubbo 原生註冊中心 |
負載均衡(Load balancing) | Ribbon(隨機、輪詢等演算法) | Dubbo 內建實現(隨機、輪詢等演算法 + 權重等特性) |
服務熔斷(Circuit Breakers) | Spring Cloud Hystrix | Spring Cloud Hystrix + Alibaba Sentinel 等 |
服務呼叫(Service-to-service calls) | Open Feign、RestTemplate | Spring Cloud 服務呼叫 + 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 開發,無論開發人員是 Dubbo 使用者還是 Spring Cloud 使用者, 都能輕鬆地駕馭,並以接近“零”成本的代價使應用向上遷移。Dubbo Spring Cloud 致力於簡化雲原生開發成本,以達成提高研發效能以及提升應用效能等目的。
1.3 Dubbo Spring Cloud 主要特性
- 面向介面代理的高效能RPC呼叫:提供高效能的基於代理的遠端呼叫能力,服務以介面為粒度,遮蔽了遠端呼叫底層細節。
- 智慧負載均衡:內建多種負載均衡策略,智慧感知下游節點健康狀況,顯著減少呼叫延遲,提高系統吞吐量。
- 服務自動註冊與發現:支援多種註冊中心服務,服務例項上下線實時感知。
- 高度可擴充套件能力:遵循微核心+外掛的設計原則,所有核心能力如Protocol、Transport、Serialization被設計為擴充套件點,平等對待內建實現和第三方實現。
- 執行期流量排程:內建條件、指令碼等路由策略,通過配置不同的路由規則,輕鬆實現灰度釋出,同機房優先等功能。
- 視覺化的服務治理與運維:提供豐富服務治理、運維工具:隨時查詢服務元資料、服務健康狀態及呼叫統計,實時下發路由策略、調整配置引數。
1.4 Spring Cloud 為什麼需要RPC
在Spring Cloud構建的微服務系統中,大多數的開發者使用都是官方提供的Feign元件來進行內部服務通訊,這種宣告式的HTTP客戶端使用起來非常的簡潔、方便、優雅,但是有一點,在使用Feign消費服務的時候,相比較Dubbo這種RPC框架而言,效能堪憂。
雖說在微服務架構中,會講按照業務劃分的微服務獨立部署,並且執行在各自的程序中。微服務之間的通訊更加傾向於使用HTTP這種簡答的通訊機制,大多數情況都會使用REST API。這種通訊方式非常的簡潔高效,並且和開發平臺、語言無關,但是通常情況下,HTTP並不會開啟KeepAlive功能,即當前連線為短連線,短連線的缺點是每次請求都需要建立TCP連線,這使得其效率變的相當低下。
對外部提供REST API服務是一件非常好的事情,但是如果內部呼叫也是使用HTTP呼叫方式,就會顯得顯得效能低下,Spring Cloud預設使用的Feign元件進行內部服務呼叫就是使用的HTTP協議進行呼叫,這時,我們如果內部服務使用RPC呼叫,對外使用REST API,將會是一個非常不錯的選擇,恰巧,Dubbo Spring Cloud給了我們這種選擇的實現方式。
2. 實戰
本小結將會以一個簡單的入門案例,介紹一下在使用Nacos作為服務中心,使用Dubbo來實現服務提供方和服務消費方的案例。
Nacos的安裝、部署配置和使用已經在前面的章節介紹過了,這裡不再贅述,如果還有不清楚的讀者,請參考前面的Nacos系列文章:
《Spring Cloud Alibaba | Nacos服務中心初探》
《Spring Cloud Alibaba | Nacos服務註冊與發現》
《Spring Cloud Alibaba | Nacos叢集部署》
《Spring Cloud Alibaba | Nacos配置管理》
2.1 建立父工程 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
包,不然啟動會報錯。 spring-cloud-starter-dubbo
包需要注意groupId,根據具體使用的spring cloud alibaba版本依賴來確定。- 如果使用孵化版本,使用的groupId為:
org.springframework.cloud
- 如果使用畢業版本,使用的groupId為:
com.alibaba.cloud
- 如果使用孵化版本,使用的groupId為:
以上引用未指定版本,需顯示的宣告
<dependencyManagement>
2.2 建立子工程 dubbo_api
API模組,存放Dubbo服務介面和模型定義,非必要,這裡建立僅為更好的程式碼重用以及介面、模型規格控制管理。
定義抽象介面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 建立子工程 dubbo_provider ,Dubbo服務提供方
工程依賴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模組。
實現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
,千萬不要引用錯誤。這裡的@Service
註解僅宣告該Java服務(本地)實現為Dubbo服務。
配置檔案 application.yml 需要將Java服務(本地)配置為 Dubbo 服務(遠端)如下:
程式碼清單: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服務方面,推薦使用外部化配置的方式,即指定Java服務實現類的掃描基準包。
Dubbo Spring Cloud 繼承了 Dubbo Spring Boot 的外部化配置特性,也可以通過標註 @DubboComponentScan 來實現基準包掃描。
dubbo.scan.base-packages
:指定 Dubbo 服務實現類的掃描基準包dubbo.protocol
:Dubbo服務暴露的協議配置,其中子屬性name為協議名稱,port為協議埠(-1 表示自增埠,從 20880 開始)dubbo.registry
:Dubbo 服務註冊中心配置,其中子屬性address 的值 "spring-cloud://192.168.44.129",說明掛載到 Spring Cloud 註冊中心spring.application.name
:Spring 應用名稱,用於 Spring Cloud 服務註冊和發現。該值在 Dubbo Spring Cloud 加持下被視作dubbo.application.name
,因此,無需再顯示地配置dubbo.application.name
。spring.main.allow-bean-definition-overriding
:在 Spring Boot 2.1 以及更高的版本增加該設定,因為 Spring Boot 預設調整了 Bean 定義覆蓋行為。spring.cloud.nacos.discovery
:Nacos 服務發現與註冊配置,其中子屬性 server-addr 指定 Nacos 伺服器主機和埠。
建立應用主類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 建立子工程 dubbo_consumer ,服務呼叫方:
工程依賴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
:表示要訂閱服務的服務名,可以配置'*'
,代表訂閱所有服務,不推薦使用。若需訂閱多應用,使用 "," 分割。
測試介面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
。
啟動主類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 測試
啟動子工程 dubbo_provider 和子工程 dubbo_consumer ,啟動完成後,我們可以訪問Nacos控制檯的服務列表上看到兩個服務,如圖:
我們開啟瀏覽器訪問:http://localhost:8080/hello ,可以看到頁面正常顯示Hello Dubbo!
,測試成功,如圖:
3. 示例程式碼
示例程式碼-Github
示例程式碼-Gitee
4. 參考
Dubbo Spring Cloud 官方文