第一节 项目简介

  Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

  依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

 

springcloudalibaba 整合security springcloud alibaba全解_ci

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_02

 

 

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_03

 

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_04

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_05

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_06

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_07

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_08

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_09

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_10

 

 

 

 

第二章 依赖管理

Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。

 

一、版本管理规范

 

项目的版本号格式为 x.x.x 的形式,其中 x 的数值类型为数字,从 0 开始取值,且不

限于 0~9 这个范围。项目处于孵化器阶段时,第一位版本号固定使用 0,即版本号为 0.x.x

的格式。

由于 Spring Boot 1 和 Spring Boot 2 在 Actuator 模块的接口和注解有很大的变更,且

spring-cloud-commons 从 1.x.x 版本升级到 2.0.0 版本也有较大的变更,因此 Spring Cloud

Alibaba 采取跟 SpringBoot 版本号一致的版本:

 1.5.x 版本适用于 Spring Boot 1.5.x

 2.0.x 版本适用于 Spring Boot 2.0.x

 2.1.x 版本适用于 Spring Boot 2.1.x

 2.2.x 版本适用于 Spring Boot 2.2.x

下表展示了 Spring Cloud Alibaba & Spring Cloud & Spring Boot 兼容关系:

The Spring Cloud Alibaba & Spring Cloud & Spring Boot compatibility table

springcloudalibaba 整合security springcloud alibaba全解_spring_11

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_12

 

 

 

以后我们的项目选择的版本为:

 Spring Boot 2.2.3.RELEASE

 Spring Cloud Hoxton.SR3

 Spring Cloud Alibaba 2.2.0.RELEASE

 

二、依赖管理

  Spring Cloud Alibaba BOM 包含了它所使用的所有依赖的版本。如果您是 Maven Central

用户,请将我们的 BOM 添加到您的 pom.xml 中的 <dependencyManagement> 部分。 这

将允许您省略任何 Maven 依赖项的版本,而是将版本控制委派给 BOM。

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2.2.0.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

 

 

 

在下面的章节中,假设您使用的是 Spring Cloud Alibaba bom,相关 starter 依赖将不包

含版本号。

 

 

三、父项目的创建

 

  使用父项目能控制所有子项目依赖的全局版本,能有效的去除子项目里面重复的依赖,

减少出错的几率。在此,我们将创建一个父 pom,让所有的子模块都继承该父 pom。

 

3.1 spring-cloud-alibaba-examples 项目的创建

 

  spring-cloud-alibaba-examples 将作为我们子项目的最大父 pom 项目!

注意:在使用 IDEA 之前我们假设您已经设置了相应的 JDK 配置和 Maven 配置

 

3.1.1 使用 IDEA 创建一个 Maven 项目

 

创建一个新的 Maven 项目 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_13

 

 

选择 Next: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_14

 

 

 

填写下面的相关信息:

Name:spring-cloud-alibaba-examples

Location:D:\workspace\spring-cloud-alibaba-examples(不要随便放)

GroupId:com.bjsxt

Version:1.0

 

最后,点击 finish 完成创建的过程!

 

 

 

3.1.2 Spring Boot 版本的控制

 

  我们采用<parent> 的方式来导入 Spriing Boot 的版本号。

打开项目的 pom.xml 文件,添加依赖内容: 

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

 

 

这样,我们的项目就已经规定了 Spring Boot 的版本为 2.2.3.RELEASE 了。

 

 

3.1.3 Spring Cloud 版本的控制

 

我们使用依赖管理的方式来添加 Spring Cloud 的版本信息,在<properties> 里面定义版

本信息,这里面我们选择 Hoxton.SR3 这个版本!

 

<properties>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>

 

 

  之后在 <dependencyManagement> 里面添加 spring-cloud 的 bom 信息,这将允许您省略任何 Maven 依赖项的版本,而是将版本控制委派给 BOM。

 

<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>
        </dependencies>
    </dependencyManagement>

 

 

 

3.1.4 Spring Cloud Alibaba 版本的控制

 

  同样,我们使用依赖管理的方式来添加 Spring Cloud Alibaba 的版本信息。在<properties>里面定义版本信息,这里面我们选择 2.2.0.RELEASE 这个版本!

 

<properties>
...
<com-alibaba-cloud.version>2.2.0.RELEASE</com-alibaba-cloud.version>
...
</properties>

 

 

  之后在 <dependencyManagement> 里面添加 spring-cloud 的 bom 信息,这将允许您省略任何 Maven 依赖项的版本,而是将版本控制委派给 BOM。 

 

 

<dependencyManagement>
    <dependencies>
    ...
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${com-alibaba-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
....
    </dependencies>
</dependencyManagement>

 

 

3.1.4 设置为 pom 的版本方式

添加项目的打包方式: 

<packaging>pom</packaging>

 

这将保证我们的项目是以 pom 打包的。 

 

3.1.5 完整的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> 
 
<groupId>com.bjsxt</groupId>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<version>1.0</version>
<properties>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
<com-alibaba-cloud.version>2.2.0.RELEASE</com-alibaba-cloud.version>
</properties>
<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>${com-alibaba-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

 

 

3.2 项目的打包

3.2.1 删除项目里面多余的文件夹

  我们的项目仅仅是一个父 pom 文件,因此,项目只需要保留 pom.xml 即可,我们在此

可以删除 src 目录。

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_15

 

 

3.2.2 执行打包

 

使用 Maven 打包我们的项目。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_16

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_17

 

 

 

3.2.3 观察打包后的效果

 

我们打开我们 Maven 设置的本地仓库地址,如图所示:

打开 Maven 里面的 settings.xml 文件,找到该标签

springcloudalibaba 整合security springcloud alibaba全解_spring_18

 

 

发现我们本地仓库的地址位于 D 盘的 lib\jar 文件夹里面:

打开该文件夹: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_19

 

 

第三章 Nacos

 

一、什么是 Nacos?

springcloudalibaba 整合security springcloud alibaba全解_Cloud_20

 

 

  Nacos 致力于发现、配置和管理微服务。它提供了一组简单易用的特性集,帮助快速实

现动态服务发现、服务配置、服务元数据及流量管理。使用 Nacos 可以更敏捷和容易地构

建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务

范式、云原生范式) 的服务基础设施。

服务(Service)是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、

配置和管理: 

 Kubernetes Service.

 gRPC & Dubbo RPC Service.

 Spring Cloud RESTful Service.

springcloudalibaba 整合security springcloud alibaba全解_Cloud_21

 

 

二、Nacos 的关键特性

 

1.服务发现和服务健康监测 ,支持基于 DNS 和 RPC 的服务发现,支持基于传输层和

应用层的监控检查;

2.动态配置服务 ,可以以中心化、外部化和动态化的方式管理所有环境的应用配置和

服务配置,同时支持版本追踪和一键回滚等功能;

3.动态 DNS 服务 ,动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均

衡、更灵活的路由策略、流量控制以及数据中心内网的简单 DNS 解析服务;

4.服务及其元数据管理 ,管理数据中心的所有服务及元数据,包括管理服务的描述、

生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服

务的 SLA 以及最首要的 metrics 统计数据。

 

三、Nacos 的核心概念

springcloudalibaba 整合security springcloud alibaba全解_spring_22

 

 

 服务 (Service)

  服务是指一个或一组软件功能(例如特定信息的检索或一组操作的执行),其目的是不同的

客户端可以为不同的目的重用(例如通过跨进程的网络调用)。Nacos 支持主流的服务生态,

如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service.

 服务注册中心 (Service Registry)

  服务注册中心,它是服务实例及元数据的数据库。服务实例在启动时注册到服务注册表,并

在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中

心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求。

 服务元数据 (Service Metadata)

  服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由规

则、安全策略等描述服务的数据

 服务提供方 (Service Provider)

  是指提供可复用和可调用服务的应用方

 服务消费方 (Service Consumer)

  是指会发起对某个服务调用的应用方

 配置 (Configuration)

  在系统开发过程中通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独

立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更

好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理

员或者运维人员完成这个步骤。配置变更是调整系统运行时的行为的有效手段之一。

 配置管理 (Configuration Management)

  在数据中心中,系统中所有配置的编辑、存储、分发、变更管理、历史版本管理、变更审计

等所有与配置相关的活动统称为配置管理。

 名字服务 (Naming Service)

  提供分布式系统中所有对象(Object)、实体(Entity)的“名字”到关联的元数据之间的映射管理

服务,例如 ServiceName -> Endpoints Info, Distributed Lock Name -> Lock Owner/Status Info,

DNS Domain Name -> IP List, 服务发现和 DNS 就是名字服务的 2 大场景。

 配置服务 (Configuration Service)

  在服务或者应用运行过程中,提供动态配置或者元数据以及配置管理的服务提供者。

 

 

 

第三章 Nacos 注册中心

 

一、Nacos Discovery 简介

 

  使用 Spring Cloud Alibaba Nacos Discovery,可基于 Spring Cloud 的编程模型快速接入 Nacos

服务注册功能。

  服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户

端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动态扩缩

容。Nacos Discovery 可以帮助您将服务自动注册到 Nacos 服务端并且能够动态感知和刷新

某个服务实例的服务列表。除此之外,Nacos Discovery 也将服务实例自身的一些元数据信

息-例如 host,port, 健康检查 URL,主页等内容注册到 Nacos。

 

 

二、Nacos Server 安装

 nacos2.0.3:处理:


 

在使用 Nacos 之前我们首先要获取和安装 Nacos。

 

2.1 Nacos Server 的下载

 

因为 Spring Cloud Alibaba 2.2.0.RELEASE 内置的 Nacos client 版本为 1.1.4,所以我们使用这个

版本的 Nacos。Nacos 下载地址:https://github.com/alibaba/nacos/releases:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_23

 

 

我们找到 1.1.4 版本后点击:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_24

 

 

找到相关系统的压缩包,这里面我使用的是 window 系统,所以我们选择

nacos-server-1.1.4.zip 该文件,来点击下载他。

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_25

 

 

2.2 Nacos Server 目录的说明

 

将下载的 nacos-server-1.1.4 复制到我们的开发工具的文件夹里面。(没有的同学可以新建

一个,养成一个良好的习惯)

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_26

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_27

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_28

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_29

 

 

2.3 配置 Nacos Server

 

进入${Nacos}/conf 目录里面,使用文件编辑器打开 application.properties 文件,这里面我使

用的是 sublime text:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_30

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_31

 

 

  Nacos 默认使用嵌入式数据库实现数据的存储,并不方便观察数据存储的基本情况,这

里面我们修改为使用 Mysql 数据库做数据的存储,方便我们观察数据的结构。

在配置文件末尾添加如下配置: 

spring.datasource.platform=mysql

db.num=1

db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTi

meout=1000&socketTimeout=3000&autoReconnect=true

db.user=root

db.password=123456 

 

 

注意:

  •  上面的 url 地址是我的服务器地址,如果你的 mysql 安装在虚拟机或云服务器上面,就

填写真实的地址。

  •  db.user 用户名
  •  db.password 密码

2.4 Mysql 表的导入

  提示:Nacos 建议使用 5.7 以上的 Mysql 数据库,版本较低可能存储兼容性问题

我使用的 Mysql 数据库版本为 5.7

 

打开${Nacos}/conf/文件夹: 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_32

 

 

新建数据库: 

springcloudalibaba 整合security springcloud alibaba全解_ci_33

 

 

新建 Nacos 的的数据库:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_34

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_35

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_36

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_37

 

 

具体表的细节和设计,我们将在源码分析的阶段讲解。

 

2.5 Nacos Server 的启动

 

上面工作都完成后,现在我们来启动一个单机版的 Nacos 服务器。

进入到${Nacos}/bin 目录里面:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_38

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_39

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_40

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_41

 

 

 

 

三、框架的搭建

springcloudalibaba 整合security springcloud alibaba全解_spring_42

 

 

我们将使用搭建所示的测试案例。

 

3.1 创建 nacos-examples 的父项目

 

我们将为 Nacos 创建一个单独项目,方便我们来学习和管理 nacos 的相关功能。

使用 IDEA 创建一个 Maven 模块:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_43

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_44

 

 

 

点击 next:

springcloudalibaba 整合security springcloud alibaba全解_ci_45

 

 

Name:nacos-examples

其他项将会自动的填充进去。

点击 Finish 完成创建。

 

修改   nacos-examples 里面的 pom.xml 文件,在此我们引入:

  •  spring-boot-starter-web (spring-boot-web 开启的最基础的依赖)
  •  spring-cloud-alibaba-nacos-discovery(nacos 做服务发现的最基础的依赖)

 

在<dependencies>添加这 2 个依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

 

 

 

修改 nacos-examples 项目的打包方式:

<packaging>pom</packaging>

 

最后,完整的 pom.xml 文件如下所示:

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-alibaba-examples</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>provider</module>
        <module>consumer</module>
        <module>config-client</module>
    </modules>
    <artifactId>nacos-examples</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>

 

 

 

 

3.2 创建服务的提供者 provider

 

服务提供者将为以后的服务消费者提供一些接口的供远程调用。

使用 IDEA 为 nacos-examples 创建一个子模块:

springcloudalibaba 整合security springcloud alibaba全解_spring_46

 

 

将 Next 进入下一步操作:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_47

 

 

注意:我们的 parent 必须选择为 nacos-examples。

 

Name:provider(服务的提供者)

其他的项将自动的填充,不需要我们修改。

Provider 的依赖分析:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_48

 

 

我们的 provider 已经自动的从 nacos-exmaples 里面把这 2 个依赖继承过来了。

 

3.3 创建服务的消费者

服务消费者将远程调用服务提供者提供的接口。

使用 IDEA 为 nacos-examples 创建一个子模块:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_49

 

 

将 Next 进入下一步操作:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_50

 

 

注意:我们的 parent 必须选择为 nacos-examples。

Name:consumer(服务的提供者)

其他的项将自动的填充,不需要我们修改。

Consumer 的依赖分析:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_51

 

 

我们的 consumer 已经自动的从 nacos-exmaples 里面把这 2 个依赖继承过来了。

至此,我们项目的骨架已经搭建完成。如下图所示:

springcloudalibaba 整合security springcloud alibaba全解_ci_52

 

 

四、使用 Nacos 做注册中心

 

4.1 provider 项目的完善

Provider 现在还是一个空的项目,里面没有任何的数据接口。

 

4.1.1 添加一个 application.yml 配置文件

 

我们给 provider 添加一个配置文件:

springcloudalibaba 整合security springcloud alibaba全解_ci_53

 

 

文件的名称为:

springcloudalibaba 整合security springcloud alibaba全解_ci_54

 

 

完成创建后,IDEA 能自动的识别该 yml 文件。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_55

 

 

编辑该配置文件,添加如下的配置:

server:
    port: 8080
spring:
    application:
        name: provider-service
    cloud:
        nacos:
            discovery:
                server-addr: localhost:8848

 

 

 

 

配置说明:

 

  • server.port provider 服务端口为 8001 ;
  • spring.application.name 服务名称为 provider-service;
  • spring.cloud.nacos.server-addr ,指定 Nacos 注册中心的地址;

 

4.1.2 添加一个启动类

 

Provider 还没有启动类,我们需要给他添加一个。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_56

 

 

com.bjsxt 为包名,ProviderApplicaton 为类的名称,创建完成后,自动的出现:

springcloudalibaba 整合security springcloud alibaba全解_spring_57

 

 

在该类里面添加如下的代码:

 

 

@SpringBootApplication // 标记为 SpringBoot 的应用
@EnableDiscoveryClient // 启用服务发现的功能
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args) ;
}
}

 

 

4.1.3 添加一个 API 接口

 

提供者通过提供 API 接口供服务提供者调用。

在 provider 里面创建一个类:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_58

 

 

名称为 controller.EchoController

springcloudalibaba 整合security springcloud alibaba全解_ci_59

 

 

成功后,如下图所示:

添加一个接口:

 

@RestController
public class EchoController {
/**
* echo message
* @param message
* @return reply content
*/
@GetMapping("/echo/{message}")
public ResponseEntity<String> echo(@PathVariable("message")
String message){
return
ResponseEntity.ok(String.format("hello,%s",message)) ;
}
}

 

 

该接口将会对访问的人输入一个 hello,xxx。

 

4.1.4 启动 provider 测试

 

现在我们的 provider 已经准备就绪,启动看能否注册到 Nacos 上面 。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_60

 

 

发现 provider 已经启动成功了。

打开 Nacos 页面观察 provider 是否上线:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_61

 

 

服务的提供者已经成功的上线了。

 

4.2 consumer 项目的完成

 

Consumer 现在还是一个空的项目,里面没有任何的数据接口,也没有对服务的提供者进行

调用。

 

4.2.1 添加一个 application.yml 配置文件

我们给 consumer 添加一个配置文件

springcloudalibaba 整合security springcloud alibaba全解_Cloud_62

 

 

名称为:application.yml

springcloudalibaba 整合security springcloud alibaba全解_Cloud_63

 

 

 

IDEA 能自动的识别该配置文件的:

 

编辑该文件,给该文件添加如下的配置信息:

 

server:
    port: 8090
spring:
    application:
        name: consumer-service
    cloud:
       nacos:
        discovery:
            server-addr: localhost:8848

 

 

4.2.2 添加一个启动类

 

Consumer 现在还没有任何的启动类,我们需要给他添加一个。

springcloudalibaba 整合security springcloud alibaba全解_ci_64

 

 

创建成功后,如下图所示:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_65

 

 

在该类里面添加如下代码:

 

@SpringBootApplication // 标记为 SpringBoot 的应用
@EnableDiscoveryClient // 开启服务的发现功能
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args) ;
}
}

 

 

4.2.3 服务发现的测试

继续改造启动类,在里面添加如下代码:

 

@Autowired
private DiscoveryClient discoveryClient ;// 快速服务的发现
@GetMapping("/discovery/{serviceName}")
public ResponseEntity<List<String>> discovery(@PathVariable("serviceName")
String serviceName){
/**
* 通过服务的 ID / 名称得到服务的实例列表
*/
List<ServiceInstance> instances =
discoveryClient.getInstances(serviceName);
if(instances==null || instances.isEmpty()){
return ResponseEntity.notFound().build() ;
}
List<String> services = new ArrayList<>(instances.size());
instances.forEach(instance->{
services.add(instance.getHost()+":"+instance.getPort());
});
return ResponseEntity.ok(services) ;
}

 

 

  因为我们在启动类里面添加了接口,所以要必须添加@RestController 该注解来标记该类:

最后,我们启动 consumer-service 项目:

springcloudalibaba 整合security springcloud alibaba全解_ci_66

 

 

Consumer-service 已经成功了上线了。

在浏览器输入:

http://localhost:8090/discovery/provider-service

 

其中:provider-service 代表服务的名称

服务器给我们响应:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_67

 

 

代表服务已经发现成功。

输入一个不存在的服务名称:

 

http://localhost:8090/discovery/provider

 

服务器给我们响应:

springcloudalibaba 整合security springcloud alibaba全解_ci_68

 

 

代表,该服务还没有服务的提供者。

 

4.2.4 远程调用的测试

在 consumer,我们调用 provider 里面的 echo 接口

继续改造我们的启动类,注册一个 RestTemplate 对象:

 

/**
* 在容器里面注入一个 RestTempalte 对象
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate() ;
}

 

 

调用测试:

 

@Autowired
27private RestTemplate restTemplate ;
@GetMapping("/rpcv1/{message}")
public ResponseEntity<String> rpcV1(@PathVariable("message") String message){
ResponseEntity<String> responseEntity = restTemplate.getForEntity(
"http://localhost:8081/echo/{message}",
String.class,
message
);
if(responseEntity.getStatusCode()==HttpStatus.OK){
return ResponseEntity.ok(String.format("远程调用成功,结果
为%s",responseEntity.getBody())) ;
}
return ResponseEntity.badRequest().body("远程调用失败") ;
}
@GetMapping("/rpcv2/{message}")
public ResponseEntity<String> rpcV2(@PathVariable("message") String message){
List<ServiceInstance> instances =
discoveryClient.getInstances("nacos-provider");
if(instances==null || instances.isEmpty()){
return ResponseEntity.badRequest().body("当前服务没有服务的提供者") ;
}
ServiceInstance serviceInstance = instances.get(0);
String instance =
serviceInstance.getHost()+":"+serviceInstance.getPort() ;
ResponseEntity<String> responseEntity = restTemplate.getForEntity(
String.format("http://%s/echo/{message}",instance),
String.class,
message
);
if(responseEntity.getStatusCode()==HttpStatus.OK){
return ResponseEntity.ok(String.format("远程调用成功,结果
为%s",responseEntity.getBody())) ;
}
return ResponseEntity.badRequest().body("远程调用失败") ;
}
@GetMapping("/rpcv3/{message}")
public ResponseEntity<String> rpcV3(@PathVariable("message") String message){
List<ServiceInstance> instances =
28discoveryClient.getInstances("nacos-provider");
if(instances==null || instances.isEmpty()){
return ResponseEntity.badRequest().body("当前服务没有服务的提供者") ;
}
ServiceInstance serviceInstance = loadbalance(instances);
System.out.println(serviceInstance);
String instance =
serviceInstance.getHost()+":"+serviceInstance.getPort() ;
ResponseEntity<String> responseEntity = restTemplate.getForEntity(
String.format("http://%s/echo/{message}",instance),
String.class,
message
);
if(responseEntity.getStatusCode()==HttpStatus.OK){
return ResponseEntity.ok(String.format("远程调用成功,结果
为%s",responseEntity.getBody())) ;
}
return ResponseEntity.badRequest().body("远程调用失败") ;
}

 

 

其中,loadBalance 的实现逻辑为:

 

/**
* 从一个服务的实例列表里面选择一个服务的实例
* @param instances
* 实例列表
* @return
* 具体的实例
*/
private ServiceInstance loadbalance(List<ServiceInstance> instances) {
Random random = new Random(System.currentTimeMillis());
return instances.get(random.nextInt(instances.size())) ;
}

 

 

 

重启 Consummer-service:

springcloudalibaba 整合security springcloud alibaba全解_spring_69

 

 

 

在浏览器里面输入:

 

http://localhost:8090/rpc/world

 

 

服务器给我们相应的数据为:

springcloudalibaba 整合security springcloud alibaba全解_ci_70

 

 

远程调用已经成功!

 

 

五、负载均衡测试

当服务压力突然变大时,我们需要通过对服务进行弹性伸缩和动态的扩容,让服务展示更强

的并发能力和容错能力。

 

5.1 修改服务提供者的数据接口

修改服务提供者的接口,可以让我们很清晰的看到,我们当前调用的是那一台服务提供者。

让我们来修改 provider 里面 EchoController 这个类

 

springcloudalibaba 整合security springcloud alibaba全解_spring_71

 

 

代码如下:

@RestController
public class EchoController { 
 
@Value("${server.port}")
private Integer port ;
/**
* echo message
* @param message
* @return reply content
*/
@GetMapping("/echo/{message}")
public ResponseEntity<String> echo(@PathVariable("message") String
message){
return ResponseEntity.ok(String.format("hello,%s,我是服务提供
者:%s",message,port)) ;
}
}

 

因为我们在同一台机器上启动多个服务提供者,那服务提供者的端口肯定不相同,我们

在此使用 port 作为服务提供者的唯一标示。

@Value : 从 env 里面注入这个值

 

5.2 启动多个服务的提供者

先停止所有的服务:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_72

 

 

在启动一个服务的提供者:

springcloudalibaba 整合security springcloud alibaba全解_spring_73

 

 

启动成功后:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_74

 

 

启动其他 1 个:

springcloudalibaba 整合security springcloud alibaba全解_spring_75

 

 

进入编辑页面:

springcloudalibaba 整合security springcloud alibaba全解_ci_76

 

 

2 个操作:

Name:不能重复,这里我修改为 ProviderApplication-2

Program arguments:--server.port=8081 这句话的意思是,在启动该服务时,添加一个

变量: server.port=8081 ,类似我们使用这样的命令启动:

 

java -jar xxx.jar --server.port=8081

 

 

--server.port 该 值 将 会 被 添 加 到 spring 的 env 里 面 , 并 且 该 方 式 的 优 先 级 高 于

application.yml 里面的配置值。所以,系统会使用该 port 来启动服务。

修改完毕后,点击 ok。

现在启动我们的复制的 ProviderApplicaton-2:

springcloudalibaba 整合security springcloud alibaba全解_ci_77

 

 

观察 Nacos 里面的数据:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_78

 

 

服务:provider-service 已经有 2 个实例了,点击详情:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_79

 

 

 

可以手动的下线该服务。

 

5.3 测试负载均衡

 

修改 consumer 里面的 ConsumerApplication ,在里面的末尾添加如下的代码:

 

@Autowired
private LoadBalancerClient loadBalancerClient ;
@GetMapping("/choose/{serviceName}")
public ResponseEntity<String> choose(@PathVariable("serviceName") String serviceName){
ServiceInstance instance = loadBalancerClient.choose(serviceName);
System.out.println(String.format("本次选择的实例
为:%s:%s",instance.getHost(),instance.getPort()));
return ResponseEntity.ok(instance.getHost()+":"+instance.getPort()) ;
}

 

 

其中:

 LoadBalancerClient :Ribbon 提供给我们最外层的接口,使用它我们可以很轻易的实现

负载均衡。

 LoadBalancerClient.choose(serviceName):通过给定的服务名称,Ribbon 底层通过负载

均衡的算法得到一个可以进行远程的实例。

现在,启动 Consumer 进行测试:

在浏览器里面输入:

 

http://localhost:8090/choose/provider-service

 

得到:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_80

 

 刷新页面:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_81

 

 

并且后台输出:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_82

 

 

发现负载均衡已经完成。

 

5.4 更简单的远程调用测试

 

在之前,我们在 consumer 使用 RestTemplate 调用 provider 时,手动实现了负载均衡,url

的拼接:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_83

 

 

代码相当的冗余。现在,我们使用 Ribbon 的方式来实现:

在注入 RestTemplate 的方法上添加注解:

springcloudalibaba 整合security springcloud alibaba全解_ci_84

 

 

远程调用的代码变为:

@GetMapping("/rpc/ribbon/{message}")
public ResponseEntity<String> rpcByRibbon(@PathVariable("message") String
message){
ResponseEntity<String> responseEntity =
restTemplate.getForEntity("http://provider-service/echo/" + message,
String.class);
if(responseEntity.getStatusCode()==HttpStatus.OK){
return ResponseEntity.ok("调用成功,provider-service 相应给我们的数
据为:"+responseEntity.getBody()) ;
}
return ResponseEntity.badRequest().body("调用失败,provider-service 的
相应码为:"+responseEntity.getStatusCode()) ;
}

springcloudalibaba 整合security springcloud alibaba全解_Cloud_85

 

 

重启 consumer 测试:

 

在浏览器里面输入:

http://localhost:8090/rpc/ribbon/{message}

springcloudalibaba 整合security springcloud alibaba全解_spring_86

 

 

刷新测试:

springcloudalibaba 整合security springcloud alibaba全解_ci_87

 

 

负载均衡已经完成了。

 

 

六、Nacos Discovery 对外暴露的 Endpoint

 

Nacos Discovery 内部提供了一个 Endpoint, 对应的 endpoint id 为 nacos-discovery。我们通

过该 Endpoint,能获取到:

 当前服务有哪些服务订阅者 ;

 当前应用 Nacos 的基础配置信息 ;

 

6.1 给项目添加依赖

 

假设我们想看服务提供者(provider)有那些订阅者,以及 Nacos 的基础配置信息。

我们就需要给 provider 项目的 pom.xml 文件里面添加:

 

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

 

 

6.2 修改配置文件

 

Endpoint 本身对外界隐藏显示,我们需要在配置里面开启对 Endponit 的显示支持。

修改 application.yml 配置文件,在里面添加如下的配置:

 

management:
38endpoints:
web:
exposure:
include: "*"

 

 

说明:

 exposure.include:对外界保留那些 Endpoint,若是所有则使用* ;

 

6.3 查询效果

 

重启项目,浏览器访问:

http://localhost:8081/actuator/nacos-discovery

效果为:

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_88

 

 

七、Nacos Discovery Starter 更多的配置项

 

springcloudalibaba 整合security springcloud alibaba全解_spring_89

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_90

 

 

第三章 Nacos 配置中心

一、Nacos Config 简介

 

使用 Spring Cloud Alibaba Nacos Config,可基于 Spring Cloud 的编程模型快速接入 Nacos 配

置管理功能。

 

上一节 Spring Cloud Alibaba Nacos 注册中心记录了 Nacos 作为注册中心的使用方式,这节继

续记录下Nacos作为配置中心的使用方式。本节使用的Spring Cloud版本为Hoxton.SR3,

Spring

Cloud Alibaba 版本为 2.2.0.RELEASE,Spring Boot 版本为 2.2.3.RELEASE。

 

二、项目的搭建

springcloudalibaba 整合security springcloud alibaba全解_Cloud_91

 

 

  我们将在我们 nacos-examples 的基础上,搭建一个 config-client,用来今天 nacos 配置中

心的案例测试 

 

 

2.1 创建 config-client 项目

 

使用 IDEA 创建一个 Maven 模块:

springcloudalibaba 整合security springcloud alibaba全解_spring_92

 

 

 

选择 Maven:

springcloudalibaba 整合security springcloud alibaba全解_spring_93

 

点击下一步:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_94

 

 

Parent:选择 nacos-examples

Name:config-client

其他的项,保持默认。

点击 FINISH 完成创建的过程:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_95

 

 

2.2 添加依赖

 

我们的项目继承自 nacos-examples,它里面已经包含 2 个基本的依赖:

 服务注册和发现:spring-cloud-alibaba-nacos-discovery 这个是微服务里面必不可缺的组

 Web 开发相关:spring-boot-starter-web 开发 web 项目最基础的依赖

现在,我们在里面添加今天我们要学习的配置获取的组件:

 

spring-cloud-alibaba-nacos-config

 

编辑 config-client 里面的 pom.xml 文件,添加以下的内容:

 

<dependencies>

<dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-alibaba-nacos-config</artifactId>

</dependency>

</dependencies> 

 

在添加一个 mavne 的打包插件:

 

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

 

查看项目所有的依赖:

springcloudalibaba 整合security springcloud alibaba全解_ci_96

 

 

现在,项目里面已经包含上面的 3 个依赖了。

 

2.3 完整的 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config-client</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

至此,项目的搭建完成了。

 

三、在 nacos-server 里面添加配置

 

相关的工作图,如图: 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_97

 

 

Nacos-client 会从 Nacos-Server 里面获取配置文件,首先,Nacos-Server 里面需要有配

置文件才能获取。

 

新建如下所示的配置信息:

 

Data ID:

nacos-config.properties

Group :

DEFAULT_GROUP

配置格式:

Properties

配置内容:

user.name=nacos-config-properties

user.age=90 

 

打开 Nacos 的管理页面:

springcloudalibaba 整合security springcloud alibaba全解_ci_98

 

 

现在我们看见,里面还没有任何的配置信息。

点击:

springcloudalibaba 整合security springcloud alibaba全解_ci_99

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_100

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_101

 

 

点击发布,完成配置文件的发表任务: 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_102

 

 

返回后,配置信息已经发布成功: 

springcloudalibaba 整合security springcloud alibaba全解_ci_103

 

 

四、获取配置信息 

config-client项目的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>nacos-examples</artifactId>
        <groupId>com.bjsxt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>config-client</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

 

我们将演示在 config-client 里面获取上面我们写的 2 个配置信息

 

4.1 添加一个配置文件

springcloudalibaba 整合security springcloud alibaba全解_Cloud_104

 

 

文件名称为: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_105

 

 

注意:不是 application.yml ,bootstrap.yml 比 application 有更高的优先级。

Idea 能自动的识别该文件的格式:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_106

 

 

编辑该文件,添加以下内容:

server:
  port: 8070
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
        file-extension: properties
  application:
    name: config-client

 

 

 

 

配置说明:

 server.port: 服务的运行端口

spring.cloud.nacos.discovery.server-addr: 注册中心地址

spring.cloud.nacos.config.server-addr: 配置中心地址

spring.cloud.nacos.config.file-extension: 配置中心的配置属性的数据格式

spring.application.name: 应用的名称 

 

4.2 新建一个启动类 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_107

 

 

名称为:com.bjsxt.ConfigClientApplication 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_108

 

编辑该类:

@SpringBootApplication
@EnableDiscoveryClient
@RefreshScope
@RestController
public class ConfigClientApplication {
@Value("${user.name}")
private String userName ;
@Value("${user.age}")
private Integer userAge ;
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class,args) ;
}
/**
* 获取配置文件里面用户的信息
* @return
*/
@GetMapping("/user/info")
public ResponseEntity<String> getUser(){
return ResponseEntity.ok(
String.format("从配置中心获取的信息为:user:%s,
age:%s",userName,userAge)) ;
}
}

 

说明:

@RefreshScope:代表配置文件是可以被刷新的

@Value:从 env 里面获取配置信息

 

4.3 启动测试 

springcloudalibaba 整合security springcloud alibaba全解_spring_109

 

 

在浏览器里面输入:

 

http://localhost:8070/user/info

springcloudalibaba 整合security springcloud alibaba全解_ci_110

 

 

效果已经完成了。

 

 

五、获取配置规则

nacos 配置中心通过 namespace、dataId 和 group 来唯一确定一条配置。

 

Namespace:即命名空间。默认的命名空间为 public,我们可以在 Nacos 控制台中新建

命名空间;

dataId:即配置文件名称

Group:即配置分组,默认为 DEFAULT_GROUP,可以通过 spring.cloud.nacos.config.group

配置。

其中:dataId 是最关键的配置字段:格式如下:

springcloudalibaba 整合security springcloud alibaba全解_ci_111

 

 

说明:

 prefix 默 认 为 spring.application.name 的 值 , 也 可 以 通 过 配 置 项

spring.cloud.nacos.config.prefix 来配置;

 spring.profiles.active 即为当前环境对应的 profile。注意,当 spring.profiles.active 为空时,

对应的连接符-也将不存在,dataId 的拼接格式变成${prefix}.${file-extension};

 file-extension 为 配 置 内 容 的 数 据 格 式 , 可 以 通 过 配 置 项 spring.cloud.nacos.config.file-extension 来配置。

这就是上面我们为什么能获得到配置的原因了。

 

 

六、配置划分实战 

springcloudalibaba 整合security springcloud alibaba全解_spring_112

 

 

Nacos 配置中心的 namespace、dataId 和 group 可以方便灵活地划分配置。比如,我们现在

有一个项目需要开发,项目名称为 bjsxt,项目开发人员分为两个组:GROUP_A 和 GROUP_B,

项目分为三个环境:开发环境 dev、测试环境 test 和生产环境 prod。

Bjsxt->GRUOR_A->dev

 

6.1 在 Nacos 控制台中新建一个名称为 bjsxt 的命名空间

springcloudalibaba 整合security springcloud alibaba全解_ci_113

 

 

点击新建命令空间:

填写以下的内容: 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_114

 

 

点击确定,完成创建。

完成后,如图所示:

springcloudalibaba 整合security springcloud alibaba全解_spring_115

 

 

新建完成后:我们看见它自动帮我们生产了一个 ID:

 

8defab18-df88-49e5-b13e-526f89da87ad

 

记录该 ID 值。

 

6.2 在 Nacos 新建配置 

springcloudalibaba 整合security springcloud alibaba全解_spring_116

 

 

切换完成后,点击 +:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_117

 

 

填写以上的信息。点击发布:

springcloudalibaba 整合security springcloud alibaba全解_ci_118

 

 

完成后:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_119

 

 

已经完成创建。

 

 

6.3 获取配置文件

 

修改 config-client 里的 bootstrap.yml 文件:

 

server:
    port: 8070
spring:
    cloud:
        nacos:
            discovery:
                server-addr: localhost:8848
            config: # 指定配置中心的地址和配置中心使用的数据格式
                server-addr: localhost:8848
                file-extension: yml  #properties
                group: GROUP_A  # 获取 GROUP_A 里面的配置
                namespace: 8defab18-df88-49e5-b13e-526f89da87ad # 命名空间,写 id的值
#               prefix: ${spring.application.name} # 前缀,默认为应用的名称,不需要
修改
    application:
        name: config-client
    profiles:
        active: dev # 使用的 dev 环境的配置

 

springcloudalibaba 整合security springcloud alibaba全解_ci_120

 

 

 

6.4 重启 config-client 测试 

springcloudalibaba 整合security springcloud alibaba全解_ci_121

 

 

浏览器访问: 

 

 

http://localhost:8070/user/info 

 

得到: 

springcloudalibaba 整合security springcloud alibaba全解_ci_122

 

 

配置信息已经获取成功。

 

七、配置回滚

 

Nacos 中,修改配置点击发布后会创建一个对应的历史版本快照,我们可以在 Nacos 控制台

的历史版本列表中找到这些快照。

 

7.1 动态刷新

springcloudalibaba 整合security springcloud alibaba全解_spring_123

 

 

该注解,可以刷新配置。故无需启动就能看见最新的配置信息。

 

7.2 修改配置文件 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_124

 

 

点击发布。

出现对比页面:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_125

 

 

点击确认发布:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_126

 

 

然后点击返回。

 

 

7.3 历史版本的查询

springcloudalibaba 整合security springcloud alibaba全解_Cloud_127

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_128

 

 

可以看见修改的日期。

 

7.4 回滚

将配置信息回滚为之前的版本:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_129

 

 

根据修改时间,我们将 12:38:53 的数据回滚为 12:25:12 的数据:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_130

 

 

已经自动的展示回滚的内容了,点击回滚配置: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_131

 

 

点击确认,完成回滚:

springcloudalibaba 整合security springcloud alibaba全解_spring_132

 

 

再次测试:

浏览器输入:

 

http://localhost:8070/user/info

 

 

已经回滚成功了: 

springcloudalibaba 整合security springcloud alibaba全解_spring_133

 

八、获取多个配置

 

除了通过上面的方式指定一个唯一配置外,我们还可以同时获取多个配置文件的内容。

 

 

8.1 修改 config-client 里面的配置文件

server:
  port: 8070
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
config:
  extension-configs: # 多个配置
      - dataId: test-a.yml
       group: DEFAULT_GROUP
      refresh: true
     - dataId: test-b.yml
      group: DEFAULT_GROUP
      refresh: false
# 指定配置中心的地址和配置中心使用的数据格式
#server-addr: localhost:8848
#file-extension: yml
#properties
#group: GROUP_A # 获取 GROUP_A 里面的配置
#namespace: 8defab18-df88-49e5-b13e-526f89da87ad # 命名空间,写 id 的值
##prefix: ${spring.application.name} # 前缀,默认为应用的名称,不需要修改
application:
  name: config-client
profiles:
  active: dev # 使用的 dev 环境的配置

 

说明:

  •  spring.cloud.nacos.config.extension-configs[n].dataId,指定多个配置的 dataId,必须包含

文件格式,支持 properties、yaml 或 yml;

  •  spring.cloud.nacos.config.extension-configs[n].group,指定分组;
  •  spring.cloud.nacos.config.extension-configs[n].refresh,是否支持刷新。

  上 面 的 配 置 中 , 我 们 分 别 从 DEFAULT_GROUP 中 获 取 了 config-client-a.yml 和

config-client-b.yml 配置内容,并且 config-client-a.yml 支持刷新,config-client-b.yml 不支持刷新。

 

注意

没有 namespace 的配置,言外之意就是 Nacos 目前还不支持多个配置指定不同的命名空间。

 

8.2 在 Nacos 里面完成这 2 个配置文件的创建

config-client-a.yml:

 

切换 namespace:

springcloudalibaba 整合security springcloud alibaba全解_ci_134

 

 

点击 + 完成创建: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_135

 

 

点击发布。

config-client-b.yml

 

springcloudalibaba 整合security springcloud alibaba全解_ci_136

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_137

 

 

8.3 获取配置信息

 

重启 config-client,测试:

浏览器访问: 

 

 

九、Spring Cloud Alibaba Nacos Config 常用的配置.

 

springcloudalibaba 整合security springcloud alibaba全解_spring_138

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_139

 

 

第四章 Spring Cloud Alibaba Sentinel

一、Sentinel 简介

springcloudalibaba 整合security springcloud alibaba全解_Cloud_140

 

 

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,

从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

 

Sentinel 具有以下特征:

 

  •  丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,

例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、实时熔断下

游不可用应用等。

  •  完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应

用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。

  •  广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与

Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可

快速地接入 Sentinel。

  •  完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩

展点,快速的定制逻辑。例如定制规则管理、适配数据源等。

 

二、Sentinel 控制台安装

 

  Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和

 

集群),规则管理和推送的功能。本节将详细记录何如通过 Sentinel 控制台控制 Sentinel 客

 

户端的各种行为。Sentinel 控制台的功能主要包括:流量控制、降级控制、热点配置、系统规则 和 授权规则等。

 

2.1 下载 Sentinel

springcloudalibaba 整合security springcloud alibaba全解_ci_141

 

 

找到:1.7.1 版本: 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_142

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_143

 

 

点击 sentinel-dashboard-1.7.1.jar 完成下载:

 

提示:

 

直接在 github 下载,速度非常的慢,大家可以从今天的软件目录里面去下载: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_144

 

 

2.2 启动 sentinel-dashboard

 

将下载好的 sentinel-dashboard-1.7.1.jar 复制到安装软件的目录里面。

springcloudalibaba 整合security springcloud alibaba全解_spring_145

 

 

使用:

    java -jar sentinel-dashboard-1.7.1.jar

 

来启动一个 sentinel-dashboard 的实例。

 

启动成功后:

springcloudalibaba 整合security springcloud alibaba全解_spring_146

 

 

我们可以通过浏览器访问:

  http://localhost:8080/ 

springcloudalibaba 整合security springcloud alibaba全解_ci_147

 

 

其中,用户名:sentinel

密码: sentinel

更多可用的启动参数配置:

 

java -D 参数名=参数值 -jar xx.jar

java -jar xx.jar --参数名=参数值

 

 

  • -Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;
  •  -Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456,如果省略这两个参数,默认用户和密码均为 sentinel;
  •  -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
  •  -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口

 

 

三、搭建客户端

springcloudalibaba 整合security springcloud alibaba全解_Cloud_148

 

 

刚才我们搭建了 sentinel-dashboard,我们还需要搭建一个客户端,用于测试 sentinel 的各种

功能。

我们将搭建如图所示的 Maven 项目结构:

springcloudalibaba 整合security springcloud alibaba全解_spring_149

 

 

3.1 使用 IDEA 创建子模块

springcloudalibaba 整合security springcloud alibaba全解_ci_150

 

 

选择 Maven 项目:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_151

 

 

点击 Next:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_152

 

 

 

 

Parent:选择 spring-cloud-alibaba-examples

Name:命名为 sentinel-example-client

其他的项保持默认值即可。

点击 Finish 完成创建。 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_153

 

 

3.2 添加依赖

 

修改 sentinel-example-client 里面的 pom.xml 文件:

添加以下的内容:

 

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>

 

 

 

有 2 个依赖:

  •  spring-cloud-starter-alibaba-sentinel 这是 spring cloud 和 sentinel 集成的项目
  •  spring-boot-starter-web 开启 web 最基础的依赖

添加 spring boot 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

 

 

这样,我们的项目打包好了后,可以使用 java -jar 来直接运行了。

 

3.3 完整的 pom.xml 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-example-client</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

3.4 添加一个配置文件

springcloudalibaba 整合security springcloud alibaba全解_ci_154

 

命名为: 

springcloudalibaba 整合security springcloud alibaba全解_spring_155

 

 

修改该配置文件,添加以下的配置:

 

server:
    port: 8085
spring:
    application:
        name: sentinel-client
    cloud:
        sentinel:
            transport:
                dashboard: localhost:8080
                port: 8719

 

 

 

其中:

  •  spring.cloud.sentinel.transport.dashboard 指定了 sentinel 控制台的 ip 和端口地址;
  •  spring.cloud.sentinel.transport.port 代表 sentinel 客户端和控制台通信的端口,默认为

8719,如果这个端口已经被占用,那么 sentinel 会自动从 8719 开始依次+1 扫描,直到

找到未被占用的端口。

 

3.5 添加一个启动类 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_156

 

 

名称为:com.bjsxt.SentinelClientApplication

springcloudalibaba 整合security springcloud alibaba全解_Cloud_157

 

 

添加如下的代码: 

 

@SpringBootApplication
public class SentinelClientApplication {
  public static void main(String[] args) {
    SpringApplication.run(SentinelClientApplication.class ,args) ;
  }
}

 

 

3.6 添加一个 Controller

 

springcloudalibaba 整合security springcloud alibaba全解_ci_158

 

 

名称为:controller.TestController

springcloudalibaba 整合security springcloud alibaba全解_ci_159

 

 

在 TestContrller 里面添加如下接口: 

 

@RestController
public class TestController {
    @GetMapping("/hello")
    public ResponseEntity<String> hello(){
        return ResponseEntity.ok("hello,sentinel") ;
    }
}

 

 

3.7 启动项目

springcloudalibaba 整合security springcloud alibaba全解_spring_160

 

在浏览器访问:

 

http://localhost:8080/#/dashboard/home

 

出现: 

springcloudalibaba 整合security springcloud alibaba全解_spring_161

 

 

发现并没有任何的功能。

 

此时,我们访问一下我们写的 hello 接口: 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_162

 

 

多访问几次。

 

再次访问:

springcloudalibaba 整合security springcloud alibaba全解_ci_163

 

 

控制台已经显示正常了。

 

并且,在簇点链路中可以看到刚刚那笔请求,我们可以对它进行流控、降级、授权、热点等

 

配置(控制台是懒加载的,如果没有任何请求,那么控制台也不会有任何内容)。 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_164

 

 

四、流控规则

 

流量的控制规则。

 

在簇点链路列表中,点击/hello 后面的流控按钮:

springcloudalibaba 整合security springcloud alibaba全解_spring_165

 

 

出现: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_166

 

 

  •  资 源 名 : 标 识 资 源 的 唯 一 名 称 , 默 认 为 请 求 路 径 , 也 可 以 在 客 户 端 中 使 用

@SentinelResource 配置;

  •  针 对 来 源 : Sentinel 可 以 针 对 服 务 调 用 者 进 行 限 流 , 填 写 微 服 务 名 称 即

spring.application.name,默认为 default,不区分来源;

  •  阈值类型、单机阈值:
  •    QPS(Queries-per-second,每秒钟的请求数量):当调用该 api 的 QPS 达到阈值的时候,进行限流;
  •    线程数:当调用该 api 的线程数达到阈值的时候,进行限流。
  •    是否集群:默认不集群;
  •    流控模式:
  •    直接:当 api 调用达到限流条件的时,直接限流;
  •    关联:当关联的资源请求达到阈值的时候,限流自己;
  •    链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,则进行限流)。
  •    流控效果:
  •    快速失败:直接失败;
  •    Warm Up:根据 codeFactor(冷加载因子,默认值为 3)的值,从阈值/codeFactor,经过预热时长,才达到设置的 QPS 阈值;
  •    排队等待:匀速排队,让请求匀速通过,阈值类型必须设置为 QPS,否则无效。

 

 

4.1 QPS 直接失败

 

演示下 QPS 直接失败设置及效果。点击簇点链路列表中/hello 请求后面的流控按钮:

 

springcloudalibaba 整合security springcloud alibaba全解_spring_167

 

 

  上面设置的效果是,1 秒钟内请求/hello 资源的次数达到 2 次以上的时候,进行限流。

点击新增完成该规则的设置。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_168

 

 

现在,在浏览器访问:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_169

 

 

  当手速快点的时候(1 秒超过 2 次),页面返回 Blocked by Sentinel (flow limiting)。并且响应

码为 429。

 

 

4.2 线程数直接失败

 

4.2.1 添加接口

 

在 TestController 里面新建一个接口。 

/**
* 线程直接失败
* @return
* @throws InterruptedException
*/
@GetMapping("/thread")
public ResponseEntity<String> threadMode() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
return ResponseEntity.ok("hello,sentinel!") ;
}

 

 

其中,我们添加了:

 

TimeUnit.SECONDS.sleep(1);

 

让线程睡 1s ,这样,更容易触发规则。

重启项目。

访问我们添加的 thread 的接口: 

 

http://localhost:8085/thread

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_170

 

 

发现,页面需要等待 1s 左右才会响应,这是线程 sleep 的效果。

4.2.2 新增流控规则

springcloudalibaba 整合security springcloud alibaba全解_ci_171

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_172

 

 

点击新增,完成创建。

springcloudalibaba 整合security springcloud alibaba全解_spring_173

 

 

4.2.3 测试该规则 

 

浏览器快速的访问:

http://localhost:8085/thread

 

springcloudalibaba 整合security springcloud alibaba全解_ci_174

 

 

4.3 关联

 

访问某个接口达到一定的流控规则后,开始限制本接口。

 

4.3.1 在 TestController 里面添加 api 接口 

 

@GetMapping("/test1")
public ResponseEntity<String> test1(){
return ResponseEntity.ok("hello,test1") ;
}
@GetMapping("/test2")
public ResponseEntity<String> test2(){
return ResponseEntity.ok("hello,test2") ;
}

 

 

重启项目,正常的访问 test1,test2 测试:

springcloudalibaba 整合security springcloud alibaba全解_ci_175

 

 

4.3.2 添加规则

我们想让 test1 关联 test2,也就是说,访问 test2 接口达到某种规则后,开始限流 test1 。

springcloudalibaba 整合security springcloud alibaba全解_ci_176

 

 

上述流控规则表示:当 1 秒内访问/test2 的次数大于 2 的时候,限流/test1。

springcloudalibaba 整合security springcloud alibaba全解_ci_177

 

 

 

 

4.3.3 测试规则

我们使用打开 2 个网页,密集访问/test2,然后我们手动浏览器请求/test1,看看效果。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_178

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_179

 

 

发现已经开始限流了。

 

4.4 链路

 

程序的调用可以看成为一条链路。当触发链路的某条规则后,该链路被限流。

springcloudalibaba 整合security springcloud alibaba全解_ci_180

 

 

上图从 API 出发,可以发现有 2 条链路,分别为:

Link1-->hello-->other

Link2-->hello-->other

2 条链路在调用上,限流规则互补影响。

 

springcloudalibaba 整合security springcloud alibaba全解_spring_181

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_182

 

 

4.4.2 添加接口 

 

@Autowired
private TestService testService ;
@GetMapping("/link1")
public ResponseEntity<String> link1(){
return ResponseEntity.ok(
String.format("link1,调用 test,结果
为%s",testService.hello())) ;
}
@GetMapping("/link2")
public ResponseEntity<String> lin2(){
return ResponseEntity.ok(
String.format("link2,调用 test,结果为%s",testService.hello())) ;
}

 

4.4.3 声明资源

 

我们现在把 TestService 里面的 hello 方法变成一个资源:

springcloudalibaba 整合security springcloud alibaba全解_spring_183

 

 

注意:

@SentinelResource("hello")将该方法标识为一个 sentinel 资源,名称为 hello。

然后重启测试:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_184

 

 

4.4.4 添加链路规则

点击簇点链路: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_185

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_186

 

 

在入口资源,我们使用的是 link1,点击新增,完成对规则的添加。

上述配置的意思是,当通过/link1 访问 hello 的时候,QPS 大于 2 则进行限流;言外之意就是

/link 访问 hello 请求并不受影响。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_187

 

 

4.4.5 测试该规则

 

打开 link1 ,link2 接口。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_188

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_189

 

 

访问测试 n 次,发现还是不能成功。难受!

具体的错误: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_190

 

 

4.5 预热 Warm Up

 

流控效果除了直接失败外,我们也可以选择预热 Warm Up。

springcloudalibaba 整合security springcloud alibaba全解_ci_191

 

 

sentinel 客户端的默认冷加载因子 coldFactor 为 3,即请求 QPS 从 threshold / 3 开始,经预

热时长逐渐升至设定的 QPS 阈值。

比如:

我们给 hello 资源设置该规则。


springcloudalibaba 整合security springcloud alibaba全解_Cloud_192

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_193

根据codeFactor(冷加载因子,默认为3)的值,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值

 

上面的配置意思是:对于/hello 资源,一开始的 QPS 阈值为 3,经过 10 秒后,QPS 阈值

达到 10。

新增完成后: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_194

 

 

 

快速访问/hello

http://localhost:8085/hello 

springcloudalibaba 整合security springcloud alibaba全解_ci_195

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_196

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_197

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_198

 

 

最快的手速点刷新,一开始会常看到 Blocked by Sentinel (flow limiting)的提示,10 秒后

几乎不再出现(因为你的手速很难达到 1 秒 10 下)。

4.6 排队等待

 

排队等待方式不会拒绝请求,而是严格控制请求通过的间隔时间,也即是让请求以均匀的速

度通过。

在 TestController 里面添加接口:

private static Logger logger = LoggerFactory.getLogger(TestController.class) ;
@GetMapping("/queue")
public ResponseEntity<String> queue(){
logger.info("开始处理请求");
return ResponseEntity.ok("ok") ;
}

 

 

重启项目并且访问 queue 接口: 

springcloudalibaba 整合security springcloud alibaba全解_ci_199

 

 

给 queue 添加一个限流规则:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_200

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_201

 

 

五、降级规则

 

Sentinel 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重

 

要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求

 

发生堆积。Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或

 

异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而

 

导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔

 

断(默认行为是抛出 DegradeException)。

 

当访问系统失败超过一定的次数后,对该接口进行熔断的操作。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_202

 

 

我们可以发现,降级策略分为 3 种:

  •  RT,平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的

平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口

 

(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地

 

熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超

 

出 此 阈 值 的 都 会 算 作 4900 ms , 若 需 要 变 更 此 上 限 可 以 通 过 启 动 配 置 项

 

-Dcsp.sentinel.statistic.max.rt=xxx 来配置。

  •  异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒

异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状

 

态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这

 

个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

  •  异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值

之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,

 

则结束熔断状态后仍可能再进入熔断状态。

 

5.1 RT

 

  当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms

为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,

对这个方法的调用都会自动地熔断(抛出 DegradeException) 

 

5.1.1 添加测试接口

 

@GetMapping("/rt")
public ResponseEntity<String> rt() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
return ResponseEntity.ok("ok") ;
}

 

 

5.1.2 添加降级的规则 

springcloudalibaba 整合security springcloud alibaba全解_spring_203

 

 

5.1.3 测试

 

打开 Apache jmeter 。

添加一个线程组: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_204

 

 

1 s 10 个线程同时发请求。

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_205

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_206

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_207

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_208

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_209

 

 

5.2 异常比例

 

当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值之后,资源进入降

级状态,在接下来的时间窗口内,程序都会快速失败。

 

5.2.1 添加接口 

@GetMapping("/exception")
public ResponseEntity<String> exception() throws InterruptedException {
throw new RuntimeException("就是不想成功!") ;
}

 

 

5.2.2 添加降级规则

springcloudalibaba 整合security springcloud alibaba全解_spring_210

 

 

上面的配置含义是:如果/exception 的 QPS 大于 5,并且每秒钟的请求异常比例大于 0.5

的话,那么在未来的 3 秒钟(时间窗口)内,sentinel 断路器打开,该 api 接口不可用。

也就是说,如果一秒内有 10 个请求进来,超过 5 个以上都出错,那么会触发熔断,1

秒钟内这个接口不可用。

 

 

5.2.3 测试

 

打开 Jmeter,修改请求的地址:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_211

 

 

开始测试

 

在浏览器打开:

 

http://localhost:8086/exception 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_212

 

 

直接被熔断,停止 jemter,等待 3s,在此访问: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_213

 

 

5.3 异常数

 

当策略为异常数时表示:当指定时间窗口内,请求异常数大于等于某个值时,触发降级。继

续使用上面的接口测试。

 

5.3.1 添加规则 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_214

 

 

上面的规则表示:在 60 秒内,访问/exception 请求异常的次数大于等于 5,则触发降级。

 

5.3.2 测试该规则

 

可以看到,当第 5 次访问的时候成功触发了降级。

 

六、热点规则

 

热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的数据,并对

其访问进行限制。

 

6.1 添加一个接口 

 

@GetMapping("/buy")
@SentinelResource("buy")
public ResponseEntity<String> buy(String prodName,Integer prodCount){
return ResponseEntity.ok("买" + prodCount + "份" + prodName );
}

 

 

6.2 添加热点的规则

 

对这个资源添加热点规则: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_215

 

 

上面的配置含义是:对 buy 资源添加热点规则,当第 0 个参数的值为华为的时候 QPS

阈值为 3,否则为 1。此外,如果第 0 个参数不传,那么这笔请求不受该热点规则限制。

 

 

6.3 测试效果

 

不是华为: 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_216

 

 

买 1 次后,里面限流。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_217

 

 

七、系统规则

 

系统规则则是针对整个系统设置限流规则,并不针对某个资源,设置页面如下: 

springcloudalibaba 整合security springcloud alibaba全解_ci_218

 

 

阈值类型包含以下五种:

 

 Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自

适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算

的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps minRt 估

算得出。设定参考值一般是 CPU cores 2.5。

 CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围

0.0-1.0),比较灵敏。

 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫

秒。

 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。

 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

 

八、授权规则

 

授权规则用于配置资源的黑白名单: 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_219

 

 

上述配置表示:只有 appA 和 appB 才能访问 test1 资源。

 

第四章 Spring Cloud Alibaba Sentinel

 

一、@SentinelResource 简介

Sentinel 提供了@SentinelResource 注解用于定义资源,并提供可选的异常回退和 Block 回退。

 

异常回退指的是@SentinelResource 注解标注的方法发生 Java 异常时的回退处理;Block 回退

 

指的是当@SentinelResource 资源访问不符合 Sentinel 控制台定义的规则时的回退(默认返回

 

Blocked by Sentinel (flow limiting))。这节简单记录下该注解的用法。

 

springcloudalibaba 整合security springcloud alibaba全解_ci_220

 

 

2.1 搭建 sentinel-example

 

我们将在 sentinel-example 里面演示所有@SentinelResource 的的功能。

 

2.1.4 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>sentinel-examples</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>

 

 

2.1.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_Cloud_221

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_222

 

 

2.1.2 添加依赖 

 

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

 

 

 Spring-boot-stater-web 是开发 web 最基础的依赖;

 spring-cloud-alibaba-nacos-discovery 是服务的发现组件

 

2.1.3 修改项目的打包方式

<packaging>pom</packaging>

 

 

 

2.2 搭建 sentinel-provider

 

Provide 是一个普通的服务的提供者。

 

2.2.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_Cloud_223

 

 

选择 Maven 项目:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_224

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_225

 

 

Parent:选择 sentinel-example

Name:sentinel-provider

 

点击 Finish,完成创建。

2.2.2 修改项目的打包方式

我们修改项目的打包方式,以后我们可以使用 jar 来发布项目。

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

 

2.2.3 完整的 pom.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-provider</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

2.3 搭建 sentinel-consumer

 

Provide 是一个普通的服务的消费者。

 

2.3.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_ci_226

 

 

点击 Next,填写以下的内容:

springcloudalibaba 整合security springcloud alibaba全解_spring_227

 

 

Parent:选择 sentinel-example

Name:sentinel-consumer

点击 Finish,完成创建。

 

2.3.2 修改 pom.xml 文件

 

我们将在该项目里面演示@SentinelResource 的功能。

 

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

 

 

我们修改项目的打包方式,以后我们可以使用 jar 来发布项目。

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

 

2.3.3 完整的 pom.xml 文件

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-consumer</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

三、完善 sentinel-provider

我们在 provider 里面添加一个模拟数据接口。

 

3.1 添加一个数据接口

 

springcloudalibaba 整合security springcloud alibaba全解_ci_228

 

 

代码如下:

@RestController
public class GoodsController {
@GetMapping("/goods/buy/{name}/{count}")
public ResponseEntity<String> buy(
@PathVariable("name") String name,
@PathVariable("count") Integer count) {
return ResponseEntity.ok(String.format("购买%d 份%s", count, name));
}
}

 

 

3.2 添加配置文件

server:
    port: 8081
spring:
    application:
        name: sentinel-provider
cloud:
    nacos:
        discovery:
            server-addr: localhost:8848

 

 

 

仅仅是为了让服务能注册到注册中心而已。

 

 

3.3 添加一个启动类 

springcloudalibaba 整合security springcloud alibaba全解_ci_229

 

 

代码如下:

 

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelProviderApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelProviderApplication.class ,args) ;
}
}

 

 

3.4 启动测试

 

在启动之前,我们必须保证 Nacos 已经启动成功。

springcloudalibaba 整合security springcloud alibaba全解_ci_230

 

 

测试接口:

 

http://localhost:8081/goods/buy/huawei/1

springcloudalibaba 整合security springcloud alibaba全解_Cloud_231

 

 

四、完善 sentinel-consumer

 

4.1 调用服务提供者 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_232

 

 

代码如下:

 

@RestController
public class BuyController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("buy/{name}/{count}")
@SentinelResource(value = "buy", fallback = "buyFallback", blockHandler =
"buyBlock")
public ResponseEntity<String> buy(@PathVariable String name, @PathVariable
Integer count) {
if (count >= 20) {
throw new IllegalArgumentException("购买数量过多");
}
if ("miband".equalsIgnoreCase(name)) {
throw new NullPointerException("已售罄");
}
Map<String, Object> params = new HashMap<>(2);
params.put("name", name);
params.put("count", count);
return ResponseEntity.ok(
this.restTemplate.getForEntity("http://sentinel-provider/goods/buy/{name}/{
count}", String.class, params).getBody());
}
// 异常回退
public ResponseEntity<String> buyFallback(@PathVariable String name,
@PathVariable Integer count, Throwable throwable) {
return ResponseEntity.ok(
String.format("【进入 fallback 方法】购买%d 份%s 失败,%s", count,
name, throwable.getMessage()));
}
// sentinel 回退
public ResponseEntity<String> buyBlock(@PathVariable String name,
@PathVariable Integer count, BlockException e) {
return ResponseEntity.ok(String.format("【进入 blockHandler 方法】购买%d
份%s 失败,当前购买人数过多,请稍后再试", count, name));
}
}

 

 

4.2 添加配置文件

springcloudalibaba 整合security springcloud alibaba全解_spring_233

 

 

内容如下:

server:

  port: 8083

spring:

  application:

    name: sentinel-consumer

cloud:

  nacos:

  discovery:

  server-addr: localhost:8848

sentinel:

  transport:

  dashboard: localhost:8080

  port: 8719

 

 

4.3 添加启动类

@SpringBootApplication

@EnableDiscoveryClient

public class SentinelConsumerApplication {

public static void main(String[] args) {

SpringApplication.run(SentinelConsumerApplication.class ,args) ;

}

@LoadBalanced

@Bean

public RestTemplate restTemplate(){

return new RestTemplate() ;

}

}

4.4 启动测试

4.4.1 启动软件

在启动之前,必须保证这些软件已经启动:

 Nacos-Server

 Sentinel-Dashboard

 Sentinel-provider

准备就绪后,启动 sentine-consumer:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_234

 

4.4.2 添加流控的规则

springcloudalibaba 整合security springcloud alibaba全解_spring_235

 

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_236

 

当访问该资源,QPS 超过 2 时,抛出异常。

测试:

http://192.168.1.11:8083/buy/huawei/1

springcloudalibaba 整合security springcloud alibaba全解_Cloud_237

 

 

五、其他用法

5.1 说明

在当前类中编写回退方法会使得代码变得冗余耦合度高,我们可以将回退方法抽取出来到一

个指定类中.

 

5.2 新增 BuyBlockHandler 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_238

 

代码如下:

public class BuyBlockHandler {

// sentinel 回退

public static String buyBlock(@PathVariable String name, @PathVariable

Integer count, BlockException e) {

return String.format("【进入 blockHandler 方法】购买%d 份%s 失败,当前购买

人数过多,请稍后再试", count, name);

}

}

 

5.3 新增 BuyFallBack

 

springcloudalibaba 整合security springcloud alibaba全解_ci_239

 

代码如下:

public class BuyBlockHandler {

// sentinel 回退

public static ResponseEntity<String> buyBlock(@PathVariable String name,

@PathVariable Integer count, BlockException e) {

return ResponseEntity.ok(String.format("【进入 blockHandler 方法】购买%d

份%s 失败,当前购买人数过多,请稍后再试", count, name));

}

}

 

5.4 改造 BuyController

 

@RestController

public class BuyController {

@Autowired

private RestTemplate restTemplate;

@GetMapping("buy/{name}/{count}")

@SentinelResource(

value = "buy",

fallback = "buyFallback",

fallbackClass = BuyFallBack.class ,

blockHandler = "buyBlock",

blockHandlerClass = BuyBlockHandler.class ,

)

public ResponseEntity<String> buy(@PathVariable String name, @PathVariable

Integer count) {

if (count >= 20) {

throw new IllegalArgumentException("购买数量过多");

}

if ("miband".equalsIgnoreCase(name)) {

throw new NullPointerException("已售罄");

}

Map<String, Object> params = new HashMap<>(2);

params.put("name", name);

params.put("count", count);

return ResponseEntity.ok(

this.restTemplate.getForEntity("http://sentinel-provider/goods/buy/{name}/{

count}", String.class, params).getBody()); 

}

 

 

 

 

 

 

 

第五章 Spring Cloud Alibaba Seata

 

一、Seata 简介

 

  Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易

 

用的分布式事务服务。在 Seata 开源之前,Seata 对应的内部版本在阿里经济体内部一直扮

 

演着分布式一致性中间件的角色,帮助经济体平稳的度过历年的双 11,对各 BU 业务进行了

 

有力的支撑。经过多年沉淀与积累,商业化产品先后在阿里云、金融云进行售卖。2019.1 为

 

了打造更加完善的技术生态和普惠技术成果,Seata 正式宣布对外开源,未来 Seata 将以社

 

区共建的形式帮助其技术更加可靠与完备。

 

二、Seata-Server 的安装

 

在使用 Seata 之前,我们首先要安装 Seata-Server 服务器。

2.1 下载 Seata

由于我们使用的 spring cloud alibaba 版本为 2.2.0.RELEASE,他里面控制了 seata 的版本为

1.0.0,故我们在此下载 1.0.0 版本的 seata。

访问:

https://github.com/seata/seata/releases/tag/v1.0.0

springcloudalibaba 整合security springcloud alibaba全解_ci_240

 

 

由于我使用的是 windows 的电脑,故选择 seata-server-1.0.0.zip 该版本。

点击该文件下载。

当下载速度较慢时,大家可以从今天的软件目录里面去下载。

 

2.2 Seata-Server 目录分析

 

springcloudalibaba 整合security springcloud alibaba全解_spring_241

 

 

Bin:可执行文件目录

Conf:配置文件目录lib:依赖的 jar

LICENSE:授权文件

 

2.3 Seata 启动

 

进入{seata}/bin 目录里面,双击:

springcloudalibaba 整合security springcloud alibaba全解_spring_242

 

 

代表 seata-server 已经启动成功。

 

三、框架的搭建

 

springcloudalibaba 整合security springcloud alibaba全解_ci_243

 

 

在本示例中,我们模拟了一个用户购买货物的场景:

 StorageService 负责扣减库存数量;

 OrderService 负责保存订单;

 AccountService 负责扣减用户账户余额;

 Business 负责用户下单的整个流程处理;

 

3.1 搭建 seata-examples 项目

 

seata-examples 用来控制所有项目的依赖版本号,以及去除公共的依赖 seata。

 

3.1.1 使用 IDEA 创建 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_spring_244

选择 Maven 项目:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_245

 

 

点击 Next,添加以下的信息:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_246

 

 

Parent:选择 spring-cloud-alibaba-examples

Name:seata-examples

其他的信息保持默认即可。然后点击 Finish 即可完成创建。

 

3.1.2 添加依赖

 

打开项目的 pom.xml 文件,添加以下的依赖。

<dependencies>
<!--
服务注册-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!--web 项目的基础依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

 

 

3.1.3 完整的 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>seata-examples</artifactId>
<dependencies>
<!--
服务注册-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<!--
seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!--
web 项目的基础依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

 

 

最后,我们的项目的依赖关系如下:可以看见,我们的 seata 版本为 1.0.0 。

springcloudalibaba 整合security springcloud alibaba全解_Cloud_247

 

 

3.2 搭建 account-service 项目

 

Account-service 项目将负责扣减用户账户余额

3.2.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_ci_248

 

 

选择 Maven 项目:

springcloudalibaba 整合security springcloud alibaba全解_spring_249

 

 

点击 Next 后,填写以下的信息:

 

springcloudalibaba 整合security springcloud alibaba全解_ci_250

 

 

Parent:seata-examples

Name:account-service

其他的值保持默认即可。

 

3.2.2 添加依赖

 

我们需要使用 ORM 框架来完成对数据库的操作。在次我们需要使用 Mybatis-Plus 来操作数据库。

打开 pom.xml ,在里面添加如下内容:

<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>

 

为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

3.2.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>account-service</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

项目的依赖关系如下:

 

3.3 搭建 business-service 项目

 

在 business 将主要完成下单逻辑,包含库存的扣减,订单的创建。

 

3.3.1 使用 IDEA 创建一个 Maven 项目

 

选择 Maven 项目:

点击 Next 后,填写以下的信息:Parent:seata-examples

Name:business-service

其他的值保持默认即可。

 

3.3.2 添加依赖

为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

3.2.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata-examples</artifactId><groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>account-service</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

项目的依赖关系如下:

springcloudalibaba 整合security springcloud alibaba全解_ci_251

 

 

3.3 搭建 business-service 项目

 

在 business 将主要完成下单逻辑,包含库存的扣减,订单的创建。

 

3.3.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_Cloud_252

 

 

选择 Maven 项目:

springcloudalibaba 整合security springcloud alibaba全解_spring_253

 

 

点击 Next 后,填写以下的信息:

springcloudalibaba 整合security springcloud alibaba全解_spring_254

 

 

Parent:seata-examples

Name:business-service

其他的值保持默认即可。

 

3.3.2 添加依赖

为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

3.2.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata-examples</artifactId><groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>account-service</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

项目的依赖关系如下:

springcloudalibaba 整合security springcloud alibaba全解_ci_255

 

 

3.4 搭建 order-service 项目

 

order-service 项目将负责保存用户订单。

 

3.4.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_ci_256

 

 

选择 Maven 项目:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_257

 

 

点击 Next 后,填写以下的信息:Parent:seata-examples

Name:order-service

其他的值保持默认即可。

 

3.4.2 添加依赖

 

我们需要使用 ORM 框架来完成对数据库的操作。在次我们需要使用 Mybatis-Plus 来操作数

据库。

打开 pom.xml ,在里面添加如下内容:

<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>

 

 

为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

 

3.4.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

项目的依赖关系如下:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_258

 

 

3.5 搭建 storage-service 项目

 

storage-service 将负责扣除商品的库存。

 

3.5.1 使用 IDEA 创建一个 Maven 项目

springcloudalibaba 整合security springcloud alibaba全解_ci_259

 

 

 

点击 Next 后,填写以下的信息:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_260

 

 

Parent:seata-examples

Name:storage-service

 

其他的值保持默认即可。

 

3.5.2 添加依赖

 

我们需要使用 ORM 框架来完成对数据库的操作。在次我们需要使用 Mybatis-Plus 来操作数

据库。

打开 pom.xml ,在里面添加如下内容:

<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency></dependencies>
为了以后我们打包发布我们的项目,在此我们添加 boot-maven 的打包插件:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

3.5.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service</artifactId>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<!--MySQL 依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies><build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

项目的依赖关系如下:

 

3.6 完整的项目的

springcloudalibaba 整合security springcloud alibaba全解_Cloud_261

 

 

案例为四、代码的完善

 

4.1 数据库表导入

 

在测试分布式事务之前,我们需要先设计数据库,以及准备测试数据。

新建数据库,命名为:seata

springcloudalibaba 整合security springcloud alibaba全解_ci_262

 

 

导入 Sql:

Sql 文件在今天的软件文件夹里面:

导入该 sql:点击开始,进行导入。

成功后,发现成功的条数为:

表有如下:account :用户的账号表

Order:订单表;

Stoage:商品的库存表;

undo_log:回滚事务表,SEATA AT 模式需要 UNDO_LOG 表。

4.2 模型对象和 Mapper 对象生成

使用 IDEA 连接数据库:

springcloudalibaba 整合security springcloud alibaba全解_spring_263

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_264

 

 

提示:

若大家没有安装 mybatis 的代码生成插件,可以在今天的软件文件夹里面下载安装。

 Account_tbl:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_265

 

 

 Order_tbl:

springcloudalibaba 整合security springcloud alibaba全解_ci_266

 

 

 Storage_tbl:

代码生成完毕后:

4.3 storage-service 代码的完善

4.3.1 接口设计

在 storage-service 里面,主要完成对库存的扣减。

新建一个接口:命名为:StorageService,代码如下:

代码如下:

public interface StorageService {

/**

* 扣减商品的库存

* @param commodityCode

* 商品的编码

* @param count

* 扣减商品的数量

*/

void deduct(String commodityCode, int count);

}

 

4.3.2 实现该接口

springcloudalibaba 整合security springcloud alibaba全解_spring_267

 

 

名称为:impl.StorageService,代码的实现如下:

 

@Service
public class StorageServiceImpl implements StorageService {
private static Logger logger = LoggerFactory.getLogger(StorageServiceImpl.class);
@Autowired
private StorageTblMapper storageTblMapper;
@Override
public void deduct(String commodityCode, int count) {
logger.info("开始扣减库存,商品编码:{},数量:{}", commodityCode, count);
StorageTbl storageTbl = storageTblMapper.selectOne(
new LambdaQueryWrapper<StorageTbl>()
.eq(StorageTbl::getCommodityCode, commodityCode));
int idleCount = storageTbl.getCount() - count;
if (idleCount < 0) {
throw new RuntimeException("库存不足");
}
storageTbl.setCount(idleCount);
storageTblMapper.updateById(storageTbl);
logger.info("库存扣减成功,商品编码:{},剩余数量:{}", commodityCode, idleCount);
}
}

 

 

4.3.3 使用 Restful 暴露此接口

springcloudalibaba 整合security springcloud alibaba全解_spring_268

 

 

添加一个 Controller

代码如下:

@RestController
public class StorageController {
private static Logger logger = LoggerFactory.getLogger(StorageController.class) ;
@Autowired
private StorageService storageService ;
/**
* 扣减商品的库存
* @param commodityCode 商品的编码
* @param count 商品的数量
* @return
*/
@GetMapping("/deduct/{commodityCode}/{count}")
public ResponseEntity<Void> deduct(
@PathVariable("commodityCode") String commodityCode,
@PathVariable("count") Integer count){
logger.info("Account Service ... xid: " + RootContext.getXID());
// 开始扣减库存
storageService.deduct(commodityCode , count);
return ResponseEntity.ok().build() ;
}
}

 

4.3.4 添加配置文件

在 resource 目录里面新建配置文件:

springcloudalibaba 整合security springcloud alibaba全解_spring_269

 

 

内容如下:

server:
    port: 18084
spring:
    application:
        name: storage-service
    cloud:
        alibaba:
            seata:
                tx-service-group: storage-service
            nacos:
                discovery:
                    server-addr: localhost:8848
    datasource:
        name: storageDataSource
        type: com.alibaba.druid.pool.DruidDataSource
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
        url:jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC
        druid:
            max-active: 20
            min-idle: 2
            initial-size: 2
seata:
    service:
        vgroup-mapping:
            account-service: default
    grouplist:
        default: 127.0.0.1:8091
    disable-global-transaction: false
    enabled: true
mybatis-plus:
    mapper-locations: classpath:/mapper/*.xml

 

 

4.3.5 添加启动类

springcloudalibaba 整合security springcloud alibaba全解_Cloud_270

 

 

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.bjsxt.mapper")
public class StorageServiceApplication {
public static void main(String[] args) {
SpringApplication.run(StorageServiceApplication.class ,args) ;
}
}

 

4.3.6 启动项目测试

启动项目后,打印该日志,说明连接 seata-server 成功。4.4 account-service 代码的完善

4.4.1 接口设计

在 account-service 里面,主要完成对用户余扣减。

新建一个接口:

命名为:AccountService,代码如下:

代码如下:

 

public interface AccountService {

/**

* 从用户的账号扣减金额

* @param userId

* 用户的 Id

* @param money

* 金额

*/

void debit(String userId, int money);

}

 

4.4.2 实现该接口

 

名称为:impl.StorageService,代码的实现如下:

 

@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountTblMapper accountTblMapper;
private static Logger logger = LoggerFactory.getLogger(AccountServiceImpl.class);
@Override
public void debit(String userId, int money) {
logger.info("准备扣减用户:{} 余额,扣减的数目为:{}", userId, money);
AccountTbl accountTbl = accountTblMapper.selectOne(
new LambdaQueryWrapper<AccountTbl>()
.eq(AccountTbl::getUserId, userId));
int idleMoney = accountTbl.getMoney() - money;
if (idleMoney < 0) {
throw new RuntimeException("用户余额不足");
}
accountTbl.setMoney(idleMoney);
accountTblMapper.updateById(accountTbl);
logger.info("扣减用户{}金额成功,剩余金额为{}", userId, money);
}
}

 

 

4.4.3 使用 Restful 暴露此接口

 

添加一个 Controller

名称为:

代码如下:

@RestController
public class AccountController {
@Autowired
private AccountService accountService ;
private static Logger logger =
LoggerFactory.getLogger(AccountController.class) ;
@GetMapping("/debit/{userId}/{money}")
public ResponseEntity<Void> debit(
@PathVariable("userId") String userId,
@PathVariable("money") Integer money){
logger.info("Account Service ... xid: " + RootContext.getXID());
// 开始扣减余额
accountService.debit(userId , money);
return ResponseEntity.ok().build() ;
}
}

 

4.4.4 添加配置文件

 

在 resource 目录里面新建配置文件:

内容如下:

server:
    port: 18085
spring:
    application:
        name: account-service
    cloud:
        alibaba:
            seata:
                tx-service-group: account-service
        nacos:
            discovery:
                server-addr: localhost:8848
datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC
    druid:
        max-active: 20
        min-idle: 2
        initial-size: 2
seata:
    service:
        vgroup-mapping:
            account-service: default
        grouplist:
            default: 127.0.0.1:8091
            disable-global-transaction: false
        enabled: true
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml

 

 

 

4.4.5 添加启动类

命名为 AccountServiceApplication ,代码如下:

 

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.bjsxt.mapper")
public class AccoutServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AccoutServiceApplication.class ,args) ;
}
}

 

 

4.4.6 启动项目测试

启动项目后,打印该日志,说明连接 seata-server 成功。4.5 order-service 代码的完善

4.5.1 接口设计

在 order-service 里面,主要完成保存用户订单的操作。

新建一个接口:

命名为:OrderService,代码如下:

代码如下:

public interface OrderService {
/**
* 创建一个订单
* @param userId 用户 id
* @param commodityCode 商品的编号
* @param orderCount 商品的数量
* @return OrderTbl
*/OrderTbl create(String userId, String commodityCode, int orderCount) ;
}

 

 

 

4.5.4 Ribbon 集成

springcloudalibaba 整合security springcloud alibaba全解_ci_271

 

 

创建一个配置类:

代码如下:

@Configuration
public class HttpUtilConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate() ;
}
}

 

 

4.5.2 实现该接口

springcloudalibaba 整合security springcloud alibaba全解_ci_272

 

 

名称为:impl.OrderService,代码的实现如下:

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderTblMapper orderTblMapper;
@Autowired
private AccountService accountService;
private static Logger logger =
LoggerFactory.getLogger(OrderServiceImpl.class);
@Override
public OrderTbl create(String userId, String commodityCode, int orderCount)
{
logger.info("准备为{}创建一个订单,商品编号为{},数量为{}", userId,
commodityCode, orderCount);
// 1 计算总金额
int orderMoney = calculate(commodityCode, orderCount);
accountService.debit(userId, orderMoney);
OrderTbl order = new OrderTbl();
order.setUserId(userId);
order.setCommodityCode(commodityCode);
order.setCount(orderCount);order.setMoney(orderMoney);
orderTblMapper.insert(order);
// INSERT INTO orders ...
return order;
}
private int calculate(String commodityCode, int orderCount) {
// 我们现在没有商品的表,在此我们把商品的价格定死
int prodPrice = 0 ;
if("HUAWEI_0001".equals(commodityCode)){ // 华为时 100
prodPrice = 100;
}else if ("XIAOMI_002".equals(commodityCode)){ // 小米时 200
prodPrice = 200 ;
}else {
prodPrice = 1000 ; // 其他为 1000
}
return orderCount * prodPrice ;
}
}

 

 

4.5.3 远程调用 account-service 的实现

springcloudalibaba 整合security springcloud alibaba全解_spring_273

 

 

创建一个 AccountService 的类,该类里面主要完成对 accout-servic 的远程调用。

名称为:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_274

 

 

/**
* 实现对账号服务的远程调用
*/
@Service
public class AccountService {
private static Logger logger = LoggerFactory.getLogger(AccountService.class) ;
/**
* 1 ribbon 的方式
*/
@Autowired
private RestTemplate restTemplate ;
/**
* 2 feign 的方式
*/
public void debit(String userId, int orderMoney) {
ResponseEntity<Void> entity = restTemplate.
getForEntity(
"http://accout-service/debit/{userId}/{orderMoney}",
Void.class,
userId,
orderMoney
);
if(entity.getStatusCode()== HttpStatus.OK){
logger.info("扣减用户{}金额成功,本次扣减的数目为{}",userId,orderMoney);
return ;
}
logger.info("扣减用户{}金额失败",userId);
throw new RuntimeException("扣减金额失败") ;
}
}

 

 

 

我们在此使用的时 Ribbon 做远程调用,下面的章节我们也会测试 Feign 。

4.5.5 使用 Restful 暴露此接口

springcloudalibaba 整合security springcloud alibaba全解_Cloud_275

 

 

代码如下:

@RestController
public class OrderController {
private static Logger logger = LoggerFactory.getLogger(OrderController.class) ;
@Autowired
private OrderService orderService ;
/**
* 创建订单
* @param userId
* 用户 Id
* @param commodityCode
* 商品的编号* @param orderCount
* 商品的数量
* @return
*/
@GetMapping("/create/{userId}/{commodityCode}/{orderCount}")
public ResponseEntity<Void> create(
@PathVariable("userId") String userId,
@PathVariable("commodityCode") String commodityCode,
@PathVariable("orderCount") int orderCount){
logger.info("Order Service ... xid: " + RootContext.getXID());
orderService.create(userId, commodityCode, orderCount) ;
return ResponseEntity.ok().build() ;
}
}

 

 

4.5.6 添加配置文件

在 resource 目录里面新建配置文件:

springcloudalibaba 整合security springcloud alibaba全解_ci_276

 

 

命名为:application.yml

内容如下:

server:
    port: 18086
spring:
    application:
        name: order-service
    cloud:
        alibaba:
            seata:
                tx-service-group: order-service
        nacos:
            discovery:
                server-addr: localhost:8848
    datasource:
        name: orderDataSource
        type: com.alibaba.druid.pool.DruidDataSource
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
        url:
jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=UTC
    druid:
        max-active: 20
        min-idle: 2
        initial-size: 2
seata:
    service:
        vgroup-mapping:
            order-service: default
        grouplist:
            default: 127.0.0.1:8091
        disable-global-transaction: false
    enabled: true
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml

 

 

4.5.7 添加启动类

springcloudalibaba 整合security springcloud alibaba全解_ci_277

 

 

命名为:OrderServiceApplication

代码如下:

@SpringBootApplication@EnableDiscoveryClient
@MapperScan("com.bjsxt.mapper")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class ,args) ;
}
}

 

4.58 启动项目测试

springcloudalibaba 整合security springcloud alibaba全解_Cloud_278

 

 

启动项目后,打印该日志,说明连接 seata-server 成功。

 

4.6 business-service 代码的完善

 

4.6.1 接口设计

在 business-service 里面,主要完成下单的逻辑,包含 2 个主要的步骤,就是对库存服务和

订单服务的远程调用。

新建一个接口:

springcloudalibaba 整合security springcloud alibaba全解_spring_279

 

 

命名为:com.bjsxt.service.BusinessService

代码如下:

 

public interface BusinessService {
/**
* 采购/下单的过程
* @param userId
* 用户的 Id
* @param commodityCode
* 商品的编码
* @param orderCount
* 商品的数量
*/
void purchase(String userId, String commodityCode, int orderCount) ;
}

 

 

4.6.2 实现该接口

 

名称为:impl.BusinessServiceImpl,代码的实现如下:

@Service
public class BusinessServiceImpl implements BusinessService {
private static Logger logger = LoggerFactory.getLogger(BusinessServiceImpl.class) ;
@Autowired
private StorageService storageService;
@Autowired
private OrderService orderService;
@Override
public void purchase(String userId, String commodityCode, int orderCount) {
logger.info("准备下单,用户:{},商品:{},数量:
{}",userId,commodityCode,orderCount);
storageService.deduct(commodityCode, orderCount);
orderService.create(userId, commodityCode, orderCount) ;
logger.info("下单完成");
}
}

 

 

4.6.3 远程调用 storage-service 的实现

springcloudalibaba 整合security springcloud alibaba全解_ci_280

 

 

创建一个 StorageService

@Service
public class StorageService {
private static Logger logger = LoggerFactory.getLogger(StorageService.class) ;
/**
* 1 采用 Ribbon 的形式
*/
@Autowired
private RestTemplate restTemplate ;
/**
* 2 采用 Feign 的形式
*/
public void deduct(String commodityCode, int orderCount) {
ResponseEntity<Void> entity = restTemplate.
getForEntity(
"http://storage-service/debut/{commodityCode}/{orderCount}",
Void.class,
commodityCode,
orderCount
);
if (entity.getStatusCode()== HttpStatus.OK){
logger.info("扣减库存成功,商品编号为{},本次扣减的数量为{}",commodityCode,orderCount);
return;
}
throw new RuntimeException("扣减库存失败") ;}
}

 

 

 

我们在此使用的时 Ribbon 做远程调用,下面的章节我们也会测试 Feign 。

 

4.6.4 远程调用 order-service

springcloudalibaba 整合security springcloud alibaba全解_spring_281

 

 

新建一个类:

 

代码如下:

 

@Service
public class OrderService {
private static Logger logger = LoggerFactory.getLogger(StorageService.class) ;
/**
* 1 采用 Ribbon 的形式
*/
@Autowired
private RestTemplate restTemplate ;
/**
* 2 采用 Feign 的形式
*/
public void create(String userId, String commodityCode, int orderCount) {
ResponseEntity<Void> entity = restTemplate.
getForEntity(
"http://order-service/create/{userId}/{commodityCode}/{orderCount}",
Void.class,
userId ,
commodityCode,
orderCount
);
if (entity.getStatusCode()== HttpStatus.OK){
logger.info("订单创建成功,用户为{} ,商品编号为{},本次扣减的数量为{}",userId ,
commodityCode,orderCount);
return;}
throw new RuntimeException("订单创建失败") ;
}
}

 

 

4.6.5 集成 Ribbon

 

添加一个 HttpUtilConfig 的配置类:

springcloudalibaba 整合security springcloud alibaba全解_ci_282

 

 

代码如下:

 

@Configuration
public class HttpUtilConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate() ;
}
}

 

 

4.6.6 添加配置文件

 

在 resource 目录里面新建配置文件:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_283

 

 

命名为:application.yml

内容如下:

server:
port: 18087
    spring:
        application:
            name: business-service
        cloud:
            alibaba:
                seata:
                    tx-service-group: business-service
            nacos:
                discovery:
                server-addr: localhost:8848
seata:
    service:
        vgroup-mapping:
            business-service: default
        grouplist:
            default: 127.0.0.1:8091
        disable-global-transaction: false
    enabled: true

 

 

4.6.7 添加启动类

 

命名为:BusinessServiceApplication

代码如下:

 

@SpringBootApplication
@EnableDiscoveryClient
public class BusinessServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BusinessServiceApplication.class ,args) ;
}
}

 

 

4.6.8 暴露下单接口

继续改造启动类:

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class BusinessServiceApplication {
@Autowired
private BusinessService businessService ;
public static void main(String[] args) {
SpringApplication.run(BusinessServiceApplication.class ,args) ;
}
/*** 开始下单
* @param userId
* 用户的 Id
* @param commodityCode
* 商品的编号
* @param orderCount
* 商品的数量
* @return
*/
@GetMapping("/purchase/{userId}/{commodityCode}/{orderCount}")
public ResponseEntity<Void> purchase(
@PathVariable("userId") String userId,
@PathVariable("commodityCode")String commodityCode,
@PathVariable("orderCount")Integer orderCount){
businessService.purchase(userId,commodityCode,orderCount);
return ResponseEntity.ok().build() ;
}
}

 

4.6.9 启动项目测试

 

启动项目后,打印该日志,说明连接 seata-server 成功。

 

4.7 总体的调用流程如下

 

都启动完成后:

springcloudalibaba 整合security springcloud alibaba全解_ci_284

 

 

Nacos-Server:

springcloudalibaba 整合security springcloud alibaba全解_ci_285

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_286

 

 

4.8 正常下单测试

 

在浏览器里面访问:

 

http://localhost:18087/purchase/SXT_USER_1/HUAWEI_0001/1

 

代表 SXT_USER_1 购买 HUAWEI_0001 产品 1 件。

 

数据库里面:

  •  Accout_tbl 里面,SXT_USER_1 用户的金额减少 100; Storage_tbl 里面,HUAWEI_0001 的库存减少了 1;
  •  Order_Tbl 里面,创建了一条订单记录;

说明,此时远程调用时正常的。

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_287

 

 

4.9 分布式事务的演示

我们演示如图的异常:

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_288

 

 

我们可以发现,远程调用共有 3 处。

 

4.9.1 在 accout-service 服务扣减余额触发异常

 

springcloudalibaba 整合security springcloud alibaba全解_ci_289

 

 

4.9.2 重启 accout-service

 

4.9.3 还原数据库里面的数据

 

Account_Tbl:Storage_Tbl:

springcloudalibaba 整合security springcloud alibaba全解_ci_290

 

 

4.9.4 重新下单测试

 

http://localhost:18087/purchase/SXT_USER_1/HUAWEI_0001/1

springcloudalibaba 整合security springcloud alibaba全解_spring_291

 

 

数据库的数据:

springcloudalibaba 整合security springcloud alibaba全解_ci_292

 

 

Account_Tbl:Storage_Tbl:

springcloudalibaba 整合security springcloud alibaba全解_spring_293

 

 

我们发现,分布式事务产生了,accout-service 内部的异常,导致 accout_tbl 表数据回滚了。

但是,在 storage_tbl :位于 stoage-service 的事务却没有回滚。

 

4.10 使用 Seata 解决分布式问题

 

4.10.1 改造 accout-service 里面的 AccountServiceImpl

springcloudalibaba 整合security springcloud alibaba全解_ci_294

 

 

当用户的 ID 为:SXT_USER_2 时,我们抛出异常,当为其他用户时,我们正常的下单。

 

4.10.2 改造 BusinessServiceImpl

@GlobalTransactional

springcloudalibaba 整合security springcloud alibaba全解_Cloud_295

 

 

添加一个注解,看他是否能解决分布式事务的问题

4.10.3 重启测试

重启 accout-service,business-service 测试

使用 SXT_USER_1 正常的下单测试:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_296

 

 

Stoage_tbl:库存正常

Accout_Tbl:余额正常

使用 SXT_USER_2 下单测试:


springcloudalibaba 整合security springcloud alibaba全解_Cloud_297

 

 

 

 

stoage_tbl 里面的没有发生改变,数据正常

Accout_tbl 里面的数据也没有发生改变,数据正常

分布式事务测试成功了

 

五、集成 Feign 测试 Seata

 

在上面的章节中,我们使用的时 Ribbon + RestTemplate 的形式做的远程调用。下面我们来演

示 Feign 的调用方式。

 

5.1 改造 business-service

5.1.1 添加依赖

修改 business-service 项目里面的 pom.xml 文件,在里面添加依赖。

 

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
</dependencies>

 

 

5.1.2 添加 OrderServiceFeign

springcloudalibaba 整合security springcloud alibaba全解_spring_298

 

 

里面的代码如下:

 

@FeignClient("order-service")
public interface OrderServiceFeign {
@GetMapping("/create/{userId}/{commodityCode}/{orderCount}")
ResponseEntity<Void> create(
@PathVariable("userId") String userId,
@PathVariable("commodityCode") String commodityCode,
@PathVariable("orderCount") Integer orderCount);
}

 

5.1.3 添加 StorageServiceFeign

springcloudalibaba 整合security springcloud alibaba全解_spring_299

 

 

@FeignClient("storage-service")
public interface StorageServiceFeign {
@GetMapping("/deduct/{commodityCode}/{orderCount}")
ResponseEntity<Void> deduct(
@PathVariable("commodityCode") String commodityCode,
@PathVariable("orderCount") Integer orderCount
) ;
}

 

 

5.1.5 改造 OrderService

springcloudalibaba 整合security springcloud alibaba全解_spring_300

 

 

@Service
public class OrderService {
private static Logger logger = LoggerFactory.getLogger(StorageService.class) ;
/**
* 1 采用 Ribbon 的形式
*/
@Autowired
private RestTemplate restTemplate ;
@Autowired
private OrderServiceFeign orderServiceFeign ;
/**
* 2 采用 Feign 的形式
*/
public void create(String userId, String commodityCode, int orderCount){

// Ribbon
//
ResponseEntity<Void> entity = restTemplate.
//
getForEntity(
//
"http://order-service/create/{userId}/{commodityCode}/{orderCount}",
//
Void.class,
//
userId ,
//
commodityCode,
//
orderCount
//
);
//Feign
ResponseEntity<Void> entity = orderServiceFeign.create(userId, commodityCode,
orderCount);
if (entity.getStatusCode()== HttpStatus.OK){
logger.info("订单创建成功,用户为{} ,商品编号为{},本次扣减的数量为{}",userId ,
commodityCode,orderCount);
return;
}
throw new RuntimeException("订单创建失败") ;
}
}

 

 

5.1.7 改造 StorageService

springcloudalibaba 整合security springcloud alibaba全解_spring_301

 

 

代码如下:

 

@Service
public class StorageService {
private static Logger logger = LoggerFactory.getLogger(StorageService.class);
/*** 1 采用 Ribbon 的形式
*/
@Autowired
private RestTemplate restTemplate;
@Autowired
private StorageServiceFeign storageServiceFeign;
/**
* 2 采用 Feign 的形式
*/
public void deduct(String commodityCode, int orderCount) {
// Ribbon
//
ResponseEntity<Void> entity = restTemplate.
//
getForEntity(
//
"http://storage-service/deduct/{commodityCode}/{orderCount}",
//
Void.class,
//
commodityCode,
//
orderCount
//
);
//Feign
ResponseEntity<Void> entity = storageServiceFeign.deduct(commodityCode,
orderCount);
if (entity.getStatusCode() == HttpStatus.OK) {
logger.info("扣减库存成功,商品编号为{},本次扣减的数量为{}", commodityCode,
orderCount);
return;
}
throw new RuntimeException("扣减库存失败");
}
}

 

 

5.1.6 在启动类里面开启对 Feign 的支持

springcloudalibaba 整合security springcloud alibaba全解_spring_302

 

 

5.2 改造 order-service

 

5.2.1 添加依赖

在 dependencies 添加:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

 

 

5.2.2 添加接口

springcloudalibaba 整合security springcloud alibaba全解_Cloud_303

 

 

里面的代码如下:

 

@FeignClient("account-service")
public interface AccountServiceFeign {
@GetMapping("/debit/{userId}/{orderMoney}")
ResponseEntity<Void> debit(
@PathVariable("userId") String userId,
@PathVariable("orderMoney") Integer orderMoney
) ;
}

 

5.2.3 修改 AccoutService

springcloudalibaba 整合security springcloud alibaba全解_Cloud_304

 

 

/**
* 实现对账号服务的远程调用
*/
@Service
public class AccountService {
private static Logger logger = LoggerFactory.getLogger(AccountService.class) ;
/**
* 1 ribbon 的方式
*/
@Autowired
private RestTemplate restTemplate ;
@Autowired
private AccountServiceFeign accountServiceFeign ;
/**
* 2 feign 的方式*/
public void debit(String userId, int orderMoney) {
//Ribbon
//
ResponseEntity<Void> entity = restTemplate.
//
getForEntity(
//
"http://accout-service/debit/{userId}/{orderMoney}",
//
Void.class,
//
userId,
//
orderMoney
//
);
ResponseEntity<Void> entity = accountServiceFeign.debit(userId, orderMoney);
if(entity.getStatusCode()== HttpStatus.OK){
logger.info("扣减用户{}金额成功,本次扣减的数目为{}",userId,orderMoney);
return ;
}
logger.info("扣减用户{}金额失败",userId);
throw new RuntimeException("扣减金额失败") ;
}
}

 

 

5.2.4 在启动类里面添加对 Feign 的支持

springcloudalibaba 整合security springcloud alibaba全解_spring_305

 

 

5.3 重启测试

 

重启 order-service ,business-service

还原数据库数据,开始测试。

正常下单测试:

springcloudalibaba 整合security springcloud alibaba全解_ci_306

 

 

使用 SXT_USER_2 下单:

springcloudalibaba 整合security springcloud alibaba全解_ci_307

 

 

出错了,但是数据库的各个表都正常。

Seata 测试成功了。

 

第六章 Spring Cloud Alibaba Dubbo

 

一、项目简介

 

Dubbo Spring Cloud 基于 Dubbo Spring Boot 2.7.1 和 Spring Cloud 2.x 开发,无论开发人

员是 Dubbo 用户还是 Spring Cloud 用户,都能轻松地驾驭,并以接近“零”成本的代价使应

用向上迁移。Dubbo Spring Cloud 致力于简化 Cloud Native 开发成本,提高研发效能以及提

升应用性能等目的。

Dubbo Spring Cloud 首个 Preview Release,随同 Spring Cloud Alibaba `0.2.2.RELEASE` 和

0.9.0.RELEASE 一同发布,分别对应 Spring Cloud Finchley 与 Greenwich(下文分别简称为 “F”

版 和 “G” 版)

 

二、功能的完成度

 

由于 Dubbo Spring Cloud 构建在原生的 Spring Cloud 之上,其服务治理方面的能力可

认为是 Spring Cloud Plus,不仅完全覆盖 Spring Cloud 原生特性,而且提供更为稳定和成熟

的实现,特性比对如下表所示:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_308

 

 

springcloudalibaba 整合security springcloud alibaba全解_ci_309

 

 

三、框架的搭建

 

我们将搭建如图所示的项目框架

springcloudalibaba 整合security springcloud alibaba全解_spring_310

 

 

3.1 搭建 spring-cloud-dubbo-examples

 

spring-cloud-dubbo-exmaples 是一个父项目,用来给子项目控制版本和去除公共的依赖。

 

3.1.1 创建项目

 

使用 IDEA 创建一个模块:

springcloudalibaba 整合security springcloud alibaba全解_spring_311

 

 

选择 Maven:

springcloudalibaba 整合security springcloud alibaba全解_ci_312

 

 

点击 Next,进行下一步操作:

springcloudalibaba 整合security springcloud alibaba全解_spring_313

 

 

Parent:必须选择之前我们创建的 spring-cloud-alibaba-examples。

Name:spring-cloud-dubbo-examples 项目的名称

点击 Finish,完成项目的创建。

springcloudalibaba 整合security springcloud alibaba全解_ci_314

 

 

至此,spring-cloud-dubbo-examples 项目已经完成创建了。

 

3.1.2 添加依赖

 

打开该项目的 pom.xml,添加以下内容: 

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

 

 

 

3.1.3 修改项目的打包方式

 

<packaging>pom</packaging>

 

3.1.4 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>spring-cloud-dubbo-examples</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>

 

 

 

3.2 搭建 dubbo-api

dubbo-api 里面将存放用于发表服务的接口。

 

3.2.1 创建 dubbo-api 项目

使用 IDEA 创建一个子模块。 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_315

 

 

选择 Maven 项目: 

springcloudalibaba 整合security springcloud alibaba全解_spring_316

 

 

点击 Next 进行下一步操作:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_317

 

 

Parent:选择 spring-cloud-dubbo-examples

Name:名称为 dubbo-api

点击 Finish 完成项目的创建:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_318

 

 

3.2.2 完整的 pom.xml 文件如下

 

dubbo-api 的 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-dubbo-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-api</artifactId>
</project>

 

 

3.3 搭建 dubbo-provider

3.3.1 创建 dubbo-provider 项目

搭建 dubbo-provider 用来做一个服务的提供者。

使用 IDEA 创建一个模块:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_319

 

 

点击 Next,进行下一步操作:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_320

 

 

Parent:选择 spring-cloud-alibaba-examples

Name:dubbo-provider

点击 Finish,完成项目的创建。

 

3.3.2 修改 Maven 的打包方式

Maven 项目默认会被 target 目录下的 class 文件打包在一个 jar 里面,该 jar 并不能直接运行,

我们需要修改它的打包方式为 spring-boot 的打包,这样,打包后的项目将能直接被运行。

修改 pom.xml ,添加如下的内容: 

 

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

 

这样,该项目将最终被打包成为一个 jar,能直接通过 java -jar 来运行

 

3.3.3 完整的 pom.xml 文件如下

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-dubbo-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-provider</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

3.4 搭建 dubbo-consumer

 

3.4.1 创建 dubbo-provider-consumer 项目

 

搭建 dubbo-provider 用来做一个服务的提供者。

使用 IDEA 创建一个模块: 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_321

 

 

选择 Maven 项目:

springcloudalibaba 整合security springcloud alibaba全解_ci_322

 

 

点击 Next,进行下一步操作:

springcloudalibaba 整合security springcloud alibaba全解_Cloud_323

 

 

Parent:选择 spring-cloud-alibaba-examples

Name:dubbo-consumer

点击 Finish,完成项目的创建。

 

3.4.2 修改 Maven 的打包方式

 

Maven 项目默认会被 target 目录下的 class 文件打包在一个 jar 里面,该 jar 并不能直接运行,

我们需要修改它的打包方式为 spring-boot 的打包,这样,打包后的项目将能直接被运行。

修改 pom.xml ,添加如下的内容:

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 

这样,该项目将最终被打包成为一个 jar,能直接通过 java -jar 来运行

 

3.4.3 完整的 pom.xml 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-dubbo-examples</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-consumer</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

 

 

3.4.4 完整的项目结构

springcloudalibaba 整合security springcloud alibaba全解_Cloud_324

 

 

四、代码的完善

 

4.1 dubbo-api 代码的完善.

 

4.1.1 定义 Dubbo 服务接口

Dubbo 服务接口是服务提供方与消费方的远程通讯契约,通常由普通的 Java 接口

(interface)来声明。 

springcloudalibaba 整合security springcloud alibaba全解_spring_325

 

 

代码如下:

 

public interface EchoService {

String echo(String message);

}

 

4.1.2 项目的打包

 

Api 项目主要是为了把 rpc 中定义的接口发布出去。

我们可以使用 Maven 的普通打包方式把编译后的 class 文件打包为 jar。 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_326

 

 

打包成功后,项目的 jar 位于:

springcloudalibaba 整合security springcloud alibaba全解_spring_327

 

 

4.2 dubbo-provider 代码的完善

4.2.1 添加依赖

在 dubbo-provider 的 pom.xml 的 dependencies 添加以下的依赖

<dependencies>

<dependency>

<groupId>com.bjsxt</groupId>

<artifactId>dubbo-api</artifactId>

<version>1.0</version>

</dependency>

</dependencies>

 

4.2.2 实现 dubbo-api 里面定义的接口

springcloudalibaba 整合security springcloud alibaba全解_spring_328

 

 

代码的内容如下:

@Service

public class EchoServiceImpl implements EchoService {

@Override

public String echo(String message) {

return "[echo] Hello, " + message;

}

 

4.2.3 添加配置文件 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_329

 

 

内容如下:

 

dubbo:
    scan:
# dubbo 服务扫描基准包
        base-packages: com.bjsxt.service.impl
    cloud:
        subscribed-services: dubbo-provider
    protocol:
# dubbo 协议
        name: dubbo
# dubbo 协议端口( -1 表示自增端口,从 20880 开始)
        port: -1
    registry:
# 挂载到 Spring Cloud 注册中心
        address: spring-cloud://localhost
spring:
    application:
# Dubbo 应用名称
        name: dubbo-provider
    main:
# Spring Boot 2.1 需要设定
        allow-bean-definition-overriding: true
    cloud:
        nacos:
# Nacos 服务发现与注册配置
            discovery:
                server-addr: localhost:8848

 

 

4.2.4 启动类

springcloudalibaba 整合security springcloud alibaba全解_Cloud_330

 

 

代码如下:

 

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderServiceApplication.class, args) ;
}
}

 

 

4.3 dubbo-consumer 代码的完善

 

4.3.1 添加依赖

 

在 dubbo-consumer 的 pom.xml 的 dependencies 添加以下的依赖

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0</version>
</dependency>
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>

 

 

4.3.2 添加配置文件 

springcloudalibaba 整合security springcloud alibaba全解_spring_331

 

 

内容如下:

 

dubbo:
    registry:
# 挂载到 Spring Cloud 注册中心
        address: nacos://127.0.0.1:8848
    cloud:
        subscribed-services: dubbo-provider
server:
    port: 8080
spring:
    application:
# Dubbo 应用名称
        name: dubbo-consumer
    main:
# Spring Boot 2.1 需要设定
        allow-bean-definition-overriding: true
    cloud:
        nacos:
# Nacos 服务发现与注册配置
            discovery:
                server-addr: 127.0.0.1:8848

 

 

4.3.3 启动类 

springcloudalibaba 整合security springcloud alibaba全解_spring_332

 

 

代码如下: 

 

@EnableDiscoveryClient
@SpringBootApplication
@RestController
public class ConsumerServiceApplication {
@Reference
private EchoService echoService ;
public static void main(String[] args) {
SpringApplication.run(ConsumerServiceApplication.class,args) ;
}
@GetMapping("/rpc")
public ResponseEntity<String> rpc(){
return ResponseEntity.ok(String.format("调用结果
为%s",echoService.echo("info")));
}
}

 

 

4.4 远程调用测试

 启动 Nacos-Server

 启动 dubbo-provider

 启动 dubbo-consumer

 

查看 Nacos 控制台:

http://localhost:8848/nacos/ 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_333

 

 

浏览器访问: 

springcloudalibaba 整合security springcloud alibaba全解_spring_334

 

 

调用已经成功;

 

五、负载均衡调用测试

 

5.1 启动多个服务的提供者

修改服务提供者里面实现类的代码:

springcloudalibaba 整合security springcloud alibaba全解_spring_335

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_336

 

 

springcloudalibaba 整合security springcloud alibaba全解_spring_337

 

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_338

 

springcloudalibaba 整合security springcloud alibaba全解_spring_339

 

 

5.2 使用消费者负载均衡调用测试

访问:

http://localhost:8080/rpc

 

springcloudalibaba 整合security springcloud alibaba全解_Cloud_340

 

 

 

 

个人学习笔记,记录日常学习,便于查阅及加深,仅为方便个人使用。