天天看點

Spring Cloud Alibaba 分布式服務調用應用服務 WEB 通路端口Actuator Web 通路端口

Spring Cloud Alibaba 分布式服務調用

  1. 簡介

    在《Spring Cloud Alibaba 服務注冊與發現》篇中曾提到,Spring Cloud Alibaba Nacos Discovery 能無縫整合 Spring Cloud OpenFeign。換言之,Spring Cloud Alibaba 延續了 Spring Cloud 分布式服務調用的特性。除此之外,Spring Cloud Alibaba 引入了 Dubbo Spring Cloud,擴充了分布式服務調用能力,不僅能使 Apache Dubbo 和 OpenFeign 共存,還允許 Spring Cloud 标準調用底層通過 Dubbo 支援的通訊協定傳輸。無論開發人員是 Dubbo 使用者還是 Spring Cloud 使用者,都能輕松地駕馭,并以接近“零”成本的代價使應用向上遷移。Dubbo Spring Cloud 緻力于簡化 Cloud Native 開發成本,提高研發效能以及提升應用性能等目的。

  2. 學習目标

    使用 Dubbo Spring Cloud 實作 Spring Cloud 分布式服務調用

    使用 Dubbo Spring Cloud 替換 Spring Cloud 分布式服務調用底層協定

    了解 Dubbo Spring Cloud 進階特性:服務訂閱、中繼資料、Actuator

  3. 詳細内容

    快速上手:使用 Apache Dubbo

    适配整合:使用注解 @DubboTransported 适配 Spring Cloud OpenFeign 和 @LoadBalanced RestTemplate

    運維特性:示範服務訂閱、元資訊(服務、REST)以及 Actuator Endpoints

  4. 功能特性

    由于 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 Sentinel17 等

服務調用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服務調用 + [email protected]

鍊路跟蹤(Tracing) Spring Cloud Sleuth?+ Zipkin Zipkin、opentracing 等

4.1 高亮特性

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

Dubbo Spring Cloud 基于 Spring Cloud Commons 抽象實作 Dubbo 服務注冊與發現,無需添加任何外部化配置,就能輕松地橋接到所有原生 Spring Cloud 注冊中心,包括:

Nacos

Eureka

Zookeeper

Consul

注:Dubbo Spring Cloud 将在下個版本支援 Spring Cloud 注冊中心與 Dubbo 注冊中心并存,提供雙注冊機制,實作無縫遷移。

4.1.2 Dubbo 作為 Spring Cloud 服務調用

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

4.1.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.1.4 Dubbo 遷移 Spring Cloud 服務調用

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

RestTemplate遷移為 Dubbo 服務。考慮到遷移過程并非一蹴而就,是以,Dubbo Spring Cloud 提供了方案,即@DubboTransported注解。該注解能夠幫助服務消費端的 Spring Cloud Open Feign 接口以及@LoadBalanced

RestTemplateBean 底層走 Dubbo 調用(可切換 Dubbo 支援的協定),而服務提供方則隻需在原有@RestController類上追加 [email protected]注解(需要抽取接口)即可,換言之,在不調整 Feign 接口以及RestTemplateURL 的前提下,實作無縫遷移。如果遷移時間充分的話,建議使用 Dubbo 服務重構系統中的原生 Spring Cloud 服務的定義。

  1. 快速上手

    5.1 如何引入 Dubbo Spring Cloud

    Dubbo Spring Cloud 引入的方式通常有兩種,由易到難分别為:Aliyun Java Initializr 引入和 Maven pom.xml 依賴。官方推薦使用 Aliyun Java Initializr 方式引入 Dubbo Spring Cloud,以便簡化元件之間的依賴關系。

5.1.1 [偷懶] 直接在沙箱裡檢視應用代碼

點選 連結,直接通路沙箱環境,這裡會有為你準備好的案例代碼_。

5.1.2 [簡單] 通過 Aliyun Java Initializr 建立工程并引入 Dubbo Spring Cloud(推薦)

Dubbo Spring Cloud 元件的在整個 Spring Cloud Alibaba 版本和依賴最為複雜,推薦讀者使用 Aliyun Java Initializr 建構應用工程。讀者選擇偏好的 Web 浏覽器通路 Aliyun Java Initializr,其資源網址為:https://start.aliyun.com/bootstrap.html

下文以 Google Chrome 浏覽器為例,當網頁加載後,首先,在 “項目基本資訊” 部分輸入 Group :“com.alibaba.cloud” 以及 Artifact:“dubbo-provider-sample”(見下圖綠框部分)

然而,“元件依賴” 輸入框搜尋:“Dubbo”(見下圖紅箭頭部分),最後,選擇 “Spring Cloud Alibaba Dubbo”(見下圖紅框部分),如下所示:

image.png

繼續依賴其他元件:

Nacos Service Discovery - 服務注冊與發現元件

Spring Web - Spring Web MVC 元件

Spring Boot Actuator - Spring Boot Actator 元件

完整元件彙總如下圖所示:

image.png

點選 “生成” 高亮按鈕,平台将生成一個名為 “dubbo-provider-sample.zip” 的壓縮檔案,将其儲存到本地目錄,并解壓該檔案,工程目錄将随之生成。打開目錄下的 pom.xml 檔案,不難發現 Dubbo Spring Cloud Starter 聲明其中(以下 XML 内容均來自于項目根路徑中的 pom.xml 檔案):

<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
           

不過該 starter 并未指定版本,具體的版本聲明在 com.alibaba.cloud:spring-cloud-alibaba-dependencies 部分:

<dependencyManagement>
    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
           

其中,${spring-cloud-alibaba.version} 和 ${spring-boot.version} 分别為 Spring Cloud Alibaba 和 Spring Boot 元件依賴的版本,它們的版本定義在 元素中,即 2.2.1.RELEASE 和 2.3.0.RELEASE:

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>
           

如果讀者非常熟悉 Maven 依賴管理的配置方式,可以考慮 Maven pom.xml 依賴 Dubbo Spring Cloud。

5.1.3 [進階] 通過 Maven pom.xml 依賴 Dubbo Spring Cloud

如果要在您 Dubbo Spring Cloud 的項目中使用 Nacos 來實作服務注冊/發現,可将兩者 Stater 同時依賴:

<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
           

該聲明方式同樣需要聲明 com.alibaba.cloud:spring-cloud-alibaba-dependencies,内容與上小節相同,在此不再贅述。下一節将讨論如何使用 Dubbo Spring Cloud 建構服務提供者。

5.2 使用 Dubbo Spring Cloud 建構服務提供者

按照傳統的 Dubbo 開發模式,在建構服務提供者之前,第一個步驟是為服務提供者和服務消費者定義 Dubbo 服務接口。

為了確定契約的一緻性,推薦的做法是将 Dubbo 服務接口打包在第二方或者第三方的 artifact(jar)中,該 artifact 甚至無需添加任何依賴。

對于服務提供方而言,不僅通過依賴 artifact 的形式引入 Dubbo 服務接口,而且需要将其實作。對應的服務消費端,同樣地需要依賴該 artifact,并以接口調用的方式執行遠端方法。接下來的步驟則是建立 artifact。

5.2.1 建立 artifact - dubbo-sample-api

選擇合适的檔案目錄,通過 Maven 指令行工具建構 artifact dubbo-sample-api,如下所示:

mvn archetype:generate -DgroupId=com.alibaba.cloud -DartifactId=dubbo-sample-api -Dversion=0.0.1-SNAPSHOT -DinteractiveMode=false

指令執行後,名為“dubbo-sample-api” 的項目目錄生成,切換至該目錄,并使用 tree 指令(macOS 指令工具)預覽器内部接口:

% tree

.

├── pom.xml

└── src

├── main

│?? └── java

│?? └── com

│?? └── alibaba

│?? └── cloud

│?? └── App.java

└── test

└── java

└── com

└── alibaba

└── cloud

└── AppTest.java

11 directories, 3 files

其中,App.java 和 AppTest.java 檔案并非需要檔案,可将其删除。除此之外,當然最重要的是 pom.xml

4.0.0

com.alibaba.cloud

dubbo-sample-api

jar

0.0.1-SNAPSHOT

dubbo-sample-api

http://maven.apache.org

junit

junit

3.8.1

test

不難看出,Maven GAV 資訊均按照之前的指令來設定,并沒有依賴其他元件。接下來,為目前工程定義 Dubbo 服務接口。

5.2.2 定義 Dubbo 服務接口

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

package com.alibaba.cloud;

public interface EchoService {

String echo(String message);

}

該接口非常簡單,僅有一個方法,接下來将 dubbo-sample-api 部署到本地 Maven 倉庫。

5.2.3 部署 artifact - dubbo-sample-api

利用 Maven 指令, 将 dubbo-sample-api 部署到本地 Maven 倉庫:

% mvn clean install

[INFO] BUILD SUCCESS

注:如果讀者所使用機器的 JDK 版本過高的話,可能會出現錯誤提示:“不再支援源選項 5。請使用 7 或更高版本”。本例推薦選擇 JDK 8 編譯。

本地部署成功後,該 artifact 能被 Dubbo 服務提供者應用 dubbo-provider-sample 依賴。

5.2.4 依賴 artifact - dubbo-sample-api

将 artifact dubbo-sample-api 依賴資訊添加到應用 dubbo-provider-sample 中的 pom.xml:

<!-- Dubbo 服務 artifact -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>dubbo-sample-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
           

依賴增加之後,下一步實作 Dubbo 服務 -EchoService?

5.2.5 實作 Dubbo 服務

在 應用 dubbo-provider-sample 中的 com.alibaba.cloud.dubboprovidersample 包下建立實作類:

public class SimpleEchoService implements EchoService {

@Override
public String echo(String s) {
    return "[ECHO] " + s;
}
           

}

其中,@org.apache.dubbo.config.annotation.Service?是 Dubbo 服務注解,僅聲明該 Java 服務(本地)實作為 Dubbo 服務。 是以,下一步需要将其配置 Dubbo 服務(遠端)。

5.2.6 配置 Dubbo 服務提供方

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

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

同時,Dubbo 遠端服務需要暴露網絡端口,并設定通訊協定,完整的 bootstrap.yaml 配置如下所示:

dubbo:

scan:

# dubbo 服務掃描基準包

base-packages: org.springframework.cloud.alibaba.dubbo.bootstrap

protocol:

# dubbo 協定

name: dubbo

# dubbo 協定端口( -1 表示自增端口,從 20880 開始)

port: -1

spring:

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 開始)

下半部分則是 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 伺服器主機和端口

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

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

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

@EnableDiscoveryClient

@SpringBootApplication

public class DubboProviderSampleApplication {

public static void main(String[] args) {

SpringApplication.run(DubboProviderSampleApplication.class);

}

}

在引導DubboProviderSampleApplication? 之前,請提前啟動 Nacos 伺服器。 當DubboProviderSampleApplication? 啟動後,将應用dubbo-provider-sample将出現在 Nacos 控制台界面:

image.png

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

5.3 使用 Dubbo Spring Cloud 實作 Dubbo 服務消費方

由于 Java 服務僅為?EchoService、服務提供方應用 dubbo-provider-sample?以及 Nacos 伺服器均已準備完畢。由于應用建立的步驟類似,建構消費方應用 dubbo-consumer-sample 的操作不再重複。

5.3.1 依賴 artifact - dubbo-sample-api

與服務提供方 Maven 工程類,需添加 artifact dubbo-sample-api 依賴,完整的元件 Maven 依賴:

<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>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>

    <!-- Dubbo 服務 artifact -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>dubbo-sample-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
           

5.3.2 配置 Dubbo 服務消費方

Dubbo 服務消費方配置與服務提供方類似,目前應用 dubbo-consumer-sample 屬于純服務消費方,是以,所需的 boostrap.yaml 檔案配置更精簡:

dubbo:

cloud:

subscribed-services: dubbo-provider-sample

spring:

cloud:

nacos:

# Nacos 服務發現與注冊配置

discovery:

server-addr: 127.0.0.1:8848

對比應用 dubbo-provider-sample,除應用名稱?spring.application.name?存在差異外,dubbo-consumer-sample 新增了屬性?dubbo.cloud.subscribed-services?的設定。并且該值為服務提供方應用 “dubbo-provider-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 服務端口,如果 dubbo-provider-sample 和 dubbo-consumer-sample 在本地同步部署的話, 兩者 Web 端口會出現沖突,需調整 dubbo-consumer-sample application.properties 中的?server.port?和management.server.port??:

應用服務 WEB 通路端口

server.port=9090

Actuator Web 通路端口

management.server.port=9091

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

為了減少實作步驟,編輯引導類DubboConsumerSampleApplication?将 Dubbo 服務消費以及引導功能合二為一:

@EnableDiscoveryClient

@EnableAutoConfiguration

@RestController

public class DubboConsumerSampleApplication {

@Reference
private EchoService echoService;

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

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

}

運作該引導類,通過curl?指令通路 REST 資源/echo?:

% curl “http://127.0.0.1:9090/echo?message=Hello,World”

[ECHO] Hello,World

不難發現,Dubbo 服務提供方應用 dubbo-provider-sample 的EchoService?計算結果傳回到 dubbo-consumer-sample 中的 REST 資源/echo。同時,在 dubbo-provider-sample 應用日志出現了以下内容:

[DUBBO] The connection of /x.x.x.x:64051 -> /x.x.x.x:20881 is established., dubbo version: 2.7.6, current host: x.x.x.x

說明 Dubbo 服務消費端應用 dubbo-consumer-sample(端口:64051) 向服務提供方應用 dubbo-provider-sample 建立連接配接(端口:20881)。