1. 程式人生 > >Dubbo 與 Spring Cloud 完美結合

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>

注意:

  1. 必須包含spring-boot-starter-actuator包,不然啟動會報錯。
  2. spring-cloud-starter-dubbo包需要注意groupId,根據具體使用的spring cloud alibaba版本依賴來確定。

    • 如果使用孵化版本,使用的groupId為:org.springframework.cloud
    • 如果使用畢業版本,使用的groupId為:com.alibaba.cloud
  3. 以上引用未指定版本,需顯示的宣告<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 官方文