Dubbo 3.0 前瞻:重塑 Spring Cloud 服務治理


1002頭圖.png

作者 | 小馬哥

導讀:Dubbo 社區策划了【Dubbo 雲原生之路】系列文章,和大家一起回顧 Apache Dubbo 產品和社區的發展,並展望未來發展。系列文章主要涵蓋 Dubbo 技術解讀、社區運營、應用案例解析三大部分。本文為系列第 3 篇。

前言

在 Java 微服務生態中,Spring Cloud 成為了開發人員的首選技術棧,然而隨着實踐的深入和運用規模的擴大,大家逐漸意識到 Spring Cloud 的局限性。

在服務治理方面,相較於Dubbo 而言,Spring Cloud 並不成熟。遺憾的是,Dubbo 往往被部分開發者片面地視作服務治理的 RPC 框架,而非微服務基礎設施。即使是那些有意將 Spring Cloud 遷移至 Dubbo 的小伙伴,當面對其中遷移和改造的成本時,難免望而卻步。

慶幸的是,Dubbo 3.0 的到來將給這一局面帶來重要變革,未來 Dubbo Spring Cloud 將無縫對接 Dubbo 3.0 ,作為Spring Cloud Alibaba 的最核心組件,完全地擁抱 Spring Cloud 技術棧,不但無縫地整合 Spring Cloud 注冊中心,包括NacosEurekaZookeeper 以及Consul,而且完全地兼容Spring Cloud Open Feign以及 @LoadBalanced RestTemplate,本文將討論 Dubbo Spring Cloud 對 Spring Cloud 技術棧所帶來的革命性變化,由於 Spring Cloud 技術棧涵蓋的特性眾多,因此本文討論的范圍僅限於服務治理部分。

本文作為 Dubbo 3.0 的前瞻,將着重講解當前版本的 Dubbo Spring Cloud 實現,Dubbo Spring Cloud 得以實現的一個重要基礎即是我們前瞻之一提到的應用級服務發現。

應用級服務發現是 Dubbo 3.0 規划中的重要一環,是 Dubbo 與雲原生基礎設施打通、實現大規模微服務集群的基石。其實 Dubbo 社區早在 2.7.5 版本開始便探索了應用級服務發現,嘗試去優化 Dubbo 的服務發現模型,因此 Dubbo Spring Cloud 是基於 Dubbo Spring Boot 2.7.x(從 2.7.0 開始,Dubbo Spring Boot 與 Dubbo 在版本上保持一致)和 Spring Cloud 2.x 開發,而本文也將基於 2.7.x 的這個先期版本展開講解。

無論開發人員是 Dubbo 用戶還是 Spring Cloud 用戶,都能輕松地駕馭 Dubbo Spring Cloud,並以接近“零”成本的代價使應用向上遷移。Dubbo Spring Cloud 致力於簡化 Cloud Native 開發成本,提高研發效能以及提升應用性能等目的。

版本支持

由於 Spring 官方宣布 Spring Cloud Edgware(下文簡稱為 “E” 版) 將在 2019 年 8 月 1 日后停止維護 13,因此,目前 Dubbo Spring Cloud 發布版本並未對 “E” 版提供支持,僅為 “F” 版 和 “G” 版開發,同時也建議和鼓勵 Spring Cloud 用戶更新至 “F” 版 或 “G” 版。

同時,Dubbo Spring Cloud 基於 Apache Dubbo Spring Boot 2.7.x 開發(最低 Java 版本為 1.8),提供完整的 Dubbo 注解驅動、外部化配置以及 Production-Ready 的特性,點擊查看詳情

以下表格將說明 Dubbo Spring Cloud 版本關系映射關系:

Spring Cloud Spring Cloud Alibaba Spring Boot Dubbo Spring Boot
Finchley 0.2.2.RELEASE 2.0.x 2.7.1
Greenwich 2.2.1.RELEASE 2.1.x 2.7.1
Edgware 0.1.2.RELEASE 1.5.x ❌ 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 配置中心(Dubbo 2.7 開始支持配置中心,可自定義適配
服務注冊與發現(Service registration and discovery) Eureka、Zookeeper、Consul Spring Cloud 原生注冊中心(Spring Cloud 原生注冊中心,除 Eureka、Zookeeper、Consul 之外,還包括 Spring Cloud Alibaba 中的 Nacos)+Dubbo 原生注冊中心
負載均衡(Load balancing) Ribbon(隨機、輪詢等算法) Dubbo 內建實現(隨機、輪詢等算法 + 權重等特性)
服務熔斷(Circuit Breakers) Spring Cloud Hystrix Spring Cloud Hystrix +Alibaba Sentinel 等(Sentinel 已被 Spring Cloud 項目納為 Circuit Breaker 的候選實現
服務調用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服務調用 + Dubbo @Reference
鏈路跟蹤(Tracing) Spring Cloud Sleuth +Zipkin  Zipkin、opentracing 等

高亮特性

1)Dubbo 使用 Spring Cloud 服務注冊與發現

Dubbo Spring Cloud 基於 Spring Cloud Commons 抽象實現 Dubbo 服務注冊與發現,應用只需增添外部化配置屬性“dubbo.registry.address = spring-cloud://localhost,就能輕松地橋接到所有原生 Spring Cloud 注冊中心,包括:- Nacos - Eureka - Zookeeper - Consul。

:Dubbo Spring Cloud 將在下個版本支持 Spring Cloud 注冊中心與 Dubbo 注冊中心並存,提供雙注冊機制,實現無縫遷移。

2)Dubbo 作為 Spring Cloud 服務調用

默認情況,Spring Cloud Open Feign 以及@LoadBalancedRestTemplate 作為 Spring Cloud 的兩種服務調用方式。Dubbo Spring Cloud 為其提供了第三種選擇,即 Dubbo 服務將作為 Spring Cloud 服務調用的同等公民出現,應用可通過 Apache Dubbo 注解 @Service@Reference 暴露和引用 Dubbo 服務,實現服務間多種協議的通訊。同時,也可以利用 Dubbo 泛化接口輕松實現服務網關。

3)Dubbo 服務自省

Dubbo Spring Cloud 引入了全新的服務治理特性 - 服務自省(Service Introspection),其設計目的在於最大化減輕注冊中心負載,去 Dubbo 注冊元信息中心化。假設一個 Spring Cloud 應用引入 Dubbo Spring Boot Starter,並暴露 N 個 Dubbo 服務,以Dubbo Nacos 注冊中心為例,當前應用將注冊 N+1 個 Nacos 應用,除 Spring Cloud 應用本身之前,其余 N 個應用均來自於 Dubbo 服務,當 N 越大時,注冊中心負載越重。

因此,Dubbo Spring Cloud 應用對注冊中心的負載相當於傳統 Dubbo 的 N 分之一,在不增加基礎設施投入的前提下,理論上,使其集群規模擴大 N 倍。當然,未來的 Dubbo 也將提供服務自省的能力。

4)Dubbo 遷移 Spring Cloud 服務調用

盡管 Dubbo Spring Cloud 完全地保留了原生 Spring Cloud 服務調用特性,但是 Dubbo 服務治理的能力是 Spring Cloud Open Feign 所不及的,如高性能、高可用以及負載均衡穩定性等方面。因此,建議開發人員將 Spring Cloud Open Feign 或者 @LoadBalancedRestTemplate 遷移為 Dubbo 服務。

考慮到遷移過程並非一蹴而就,因此,Dubbo Spring Cloud 提供了方案,即 @DubboTransported 注解。該注解能夠幫助服務消費端的 Spring Cloud Open Feign 接口以及 @LoadBalanced RestTemplate Bean 底層走 Dubbo 調用(可切換 Dubbo 支持的協議),而服務提供方則只需在原有 @RestController 類上追加 Dubbo @Servce 注解(需要抽取接口)即可,換言之,在不調整 Feign 接口以及 RestTemplate URL 的前提下,實現無縫遷移。如果遷移時間充分的話,建議使用 Dubbo 服務重構系統中的原生 Spring Cloud 服務的定義。

簡單示例

開發 Dubbo Spring Cloud 應用的方法與傳統 Dubbo 或 Spring Cloud 應用類似,按照以下步驟就能完整地實現Dubbo 服務提供方和消費方的應用,完整的示例代碼請訪問一下資源:

1. 定義 Dubbo 服務接口

Dubbo 服務接口是服務提供方與消費方的遠程通訊契約,通常由普通的 Java 接口(interface)來聲明,如EchoService 接口:

public interface EchoService {


    String echo(String message);
}

為了確保契約的一致性,推薦的做法是將 Dubbo 服務接口打包在第二方或者第三方的 artifact(jar)中,如以上接口就存放在 artifact spring-cloud-dubbo-sample-api 之中。

對於服務提供方而言,不僅通過依賴 artifact 的形式引入 Dubbo 服務接口,而且需要將其實現。對應的服務消費端,同樣地需要依賴該 artifact,並以接口調用的方式執行遠程方法。接下來進一步討論怎樣實現 Dubbo 服務提供方和消費方。

2. 實現 Dubbo 服務提供方

1)初始化 spring-cloud-dubbo-server-sample Maven 工程

首先,創建 artifactId 名為 spring-cloud-dubbo-server-sample 的 Maven 工程,並在其 pom.xml 文件中增添 Dubbo Spring Cloud 必要的依賴:

<dependencies>
    <!-- Sample API -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dubbo-sample-api</artifactId>
        <version>${project.version}</version>
    </dependency>


    <!-- Spring Boot dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>


    <!-- Dubbo Spring Cloud Starter -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>


    <!-- Spring Cloud Nacos Service Discovery -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencie

以上依賴 artifact 說明如下:

  • spring-cloud-dubbo-sample-api: 提供 EchoService 接口的 artifact;

  • spring-boot-actuator: Spring Boot Production-Ready artifact,間接引入 spring-boot artifact;

  • spring-cloud-starter-dubbo: Dubbo Spring Cloud Starter artifact,間接引入 dubbo-spring-boot-starter 等 artifact;

  • spring-cloud-starter-alibaba-nacos-discovery: Nacos Spring Cloud 服務注冊與發現 artifact

值得注意的是,以上 artifact 未指定版本(version),因此,還需顯示地聲明 <dependencyManagement>:

<dependencyManagement>
    <dependencies>
        <!-- Spring Cloud Alibaba dependencies -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

:以上完整的 Maven 依賴配置,請參考 spring-cloud-dubbo-server-sample pom.xml 文件。

完成以上步驟之后,下一步則是實現 Dubbo 服務。

2)實現 Dubbo 服務

EchoService 作為暴露的 Dubbo 服務接口,服務提供方 spring-cloud-dubbo-server-sample 需要將其實現:

@org.apache.dubbo.config.annotation.Service
class EchoServiceImpl implements EchoService {


    @Override
    public String echo(String message) {
        return "[echo] Hello, " + message;
    }
}

其中,@org.apache.dubbo.config.annotation.Service 是 Dubbo 服務注解,僅聲明該 Java 服務(本地)實現為 Dubbo 服務。因此,下一步需要將其配置 Dubbo 服務(遠程)。

3)配置 Dubbo 服務提供方

在暴露 Dubbo 服務方面,推薦開發人員外部化配置的方式,即指定 Java 服務實現類的掃描基准包。

:Dubbo Spring Cloud 繼承了 Dubbo Spring Boot 的外部化配置特性,也可以通過標注 @DubboComponentScan 來實現基准包掃描。

同時,Dubbo 遠程服務需要暴露網絡端口,並設定通訊協議,完整的 YAML 配置如下所示:

dubbo:
  scan:
    # dubbo 服務掃描基准包
    base-packages: org.springframework.cloud.alibaba.dubbo.bootstrap
  protocol:
    # dubbo 協議
    name: dubbo
    # dubbo 協議端口( -1 表示自增端口,從 20880 開始)
    port: -1

spring:
  application:
    # Dubbo 應用名稱
    name: spring-cloud-alibaba-dubbo-server
  cloud:
    nacos:
      # Nacos 服務發現與注冊配置
      discovery:
        server-addr: 127.0.0.1:8848

以上 YAML 內容,上半部分為 Dubbo 的配置:

  • dubbo.scan.base-packages: 指定 Dubbo 服務實現類的掃描基准包;

  • dubbo.protocol: Dubbo 服務暴露的協議配置,其中子屬性 name 為協議名稱,port 為協議端口( -1 表示自增端口,從 20880 開始);

  • dubbo.registry: Dubbo 服務注冊中心配置,其中子屬性 address 的值 "spring-cloud://localhost",說明掛載到 Spring Cloud 注冊中心。

下半部分則是 Spring Cloud 相關配置:

  • spring.application.name: Spring 應用名稱,用於 Spring Cloud 服務注冊和發現。> 該值在 Dubbo Spring Cloud 加持下被視作 dubbo.application.name,因此,無需再顯示地配置 dubbo.application.name

  • spring.cloud.nacos.discovery: Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口。

以上完整的 YAML 配置文件,請參考 spring-cloud-dubbo-server-samplebootstrap.yaml 文件。

完成以上步驟后,還需編寫一個 Dubbo Spring Cloud 引導類。

4)引導 Dubbo Spring Cloud 服務提供方應用

Dubbo Spring Cloud 引導類與普通 Spring Cloud 應用並無差別,如下所示:

 @EnableDiscoveryClient @EnableAutoConfiguration public class DubboSpringCloudServerBootstrap {
public static void main(String[] args) {
    SpringApplication.run(DubboSpringCloudServerBootstrap.class);
}
}

在引導 DubboSpringCloudServerBootstrap 之前,請提前啟動 Nacos 服務器。當 DubboSpringCloudServerBootstrap 啟動后,將應用 spring-cloud-dubbo-server-sample 將出現在 Nacos 控制台界面。

當 Dubbo 服務提供方啟動后,下一步實現一個 Dubbo 服務消費方。

3. 實現 Dubbo 服務消費方

由於 Java 服務就 EchoService、服務提供方應用 spring-cloud-dubbo-server-sample 以及 Nacos 服務器均已准備完畢。Dubbo 服務消費方只需初始化服務消費方 Maven 工程 spring-cloud-dubbo-client-sample 以及消費 Dubbo 服務。

1)初始化 spring-cloud-dubbo-client-sample Maven 工程

與服務提供方 Maven 工程類,需添加相關 Maven 依賴:

<dependencyManagement>
    <dependencies>
        <!-- Spring Cloud Alibaba dependencies -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.1.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>


<dependencies>
    <!-- Sample API -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dubbo-sample-api</artifactId>
        <version>${project.version}</version>
    </dependency>


    <!-- Spring Boot dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>


    <!-- Dubbo Spring Cloud Starter -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>


    <!-- Spring Cloud Nacos Service Discovery -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependenc

與應用 spring-cloud-dubbo-server-sample 不同的是,當前應用依賴 spring-boot-starter-web,表明它屬於 Web Servlet 應用。

注:以上完整的 Maven 依賴配置,請參考 spring-cloud-dubbo-client-sample pom.xml 文件。

2)配置 Dubbo 服務消費方

Dubbo 服務消費方配置與服務提供方類似,當前應用 spring-cloud-dubbo-client-sample 屬於純服務消費方,因此,所需的外部化配置更精簡:


dubbo:
  cloud:
    subscribed-services: spring-cloud-alibaba-dubbo-server

spring:
  application:
    # Dubbo 應用名稱
    name: spring-cloud-alibaba-dubbo-client
  cloud:
    nacos:
      # Nacos 服務發現與注冊配置
      discovery:
        server-addr: 127.0.0.1:8848

對比應用 spring-cloud-dubbo-server-sample,除應用名稱 spring.application.name 存在差異外,spring-cloud-dubbo-client-sample 新增了屬性 dubbo.cloud.subscribed-services 的設置,並且該值為服務提供方應用 "spring-cloud-dubbo-server-sample"。

dubbo.cloud.subscribed-services: 用於服務消費方訂閱服務提供方的應用名稱的列表,若需訂閱多應用,使用 "," 分割。不推薦使用默認值為 "*",它將訂閱所有應用。

當應用使用屬性 dubbo.cloud.subscribed-services 默認值時,日志中將會輸出一行警告:

Current application will subscribe all services(size:x) in registry, a lot of memory and CPU cycles may be used,

thus it's strongly recommend you using the externalized property 'dubbo.cloud.subscribed-services' to specify the services

由於當前應用屬於 Web 應用,它會默認地使用 8080 作為 Web 服務端口,如果需要自定義,可通過屬性 server.port 調整。

:以上完整的 YAML 配置文件,請參考 spring-cloud-dubbo-client-sample``bootstrap.yaml 文件。

3)引導 Dubbo Spring Cloud 服務消費方應用

為了減少實現步驟,以下引導類將 Dubbo 服務消費以及引導功能合二為一:


@EnableDiscoveryClient
@EnableAutoConfiguration
@RestController
public class DubboSpringCloudClientBootstrap {


    @Reference
    private EchoService echoService;


    @GetMapping("/echo")
    public String echo(String message) {
        return echoService.echo(message);
    }


    public static void main(String[] args) {
        SpringApplication.run(DubboSpringCloudClientBootstrap.class);
    }

不僅如此,DubboSpringCloudClientBootstrap 也作為 REST Endpoint,通過暴露 /echo Web 服務,消費 Dubbo EchoService 服務。因此, 可通過 curl 命令執行 HTTP GET 方法:

$ curl http://127.0.0.1:8080/echo?message=%E5%B0%8F%E9%A9%AC%E5%93%A5%EF%BC%88mercyblitz%EF%BC%89

HTTP 響應為:

[echo] Hello, 小馬哥(mercyblitz)

以上結果說明應用 spring-cloud-dubbo-client-sample 通過消費 Dubbo 服務,返回服務提供方 spring-cloud-dubbo-server-sample 運算后的內容。

高階示例

如果您需要進一步了解 Dubbo Spring Cloud 使用細節,可參考 參考官方 Samples

其子模塊說明如下:

  • spring-cloud-dubbo-sample-api:API 模塊,存放 Dubbo 服務接口和模型定義;

  • spring-cloud-dubbo-provider-web-sample:Dubbo Spring Cloud 服務提供方示例(Web 應用);

  • spring-cloud-dubbo-provider-sample:Dubbo Spring Cloud 服務提供方示例(非 Web 應用);

  • spring-cloud-dubbo-consumer-sample:Dubbo Spring Cloud 服務消費方示例;

  • spring-cloud-dubbo-servlet-gateway-sample:Dubbo Spring Cloud Servlet 網關簡易實現示例。

問題反饋

如果您在使用 Dubbo Spring Cloud 的過程中遇到任何問題,請在此反饋內容

反饋鏈接:https://github.com/alibaba/spring-cloud-alibaba/issues

進階閱讀

關於更多的 Dubbo Spring Cloud 特性以及設計細節,請關注:

系列文章:

作者簡介

小馬哥(mercyblitz),Java 勸退師,Apache Dubbo PMC、Spring Cloud Alibaba 項目架構師。目前主要負責阿里集團中間件開源項目、微服務技術實施、架構衍進、基礎設施構建等。

阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM