springcloud 笔记

2023-10-30

提示:本学习笔记是参照尚硅谷视频写的, 视频地址


文章目录


第一章 Spring Cloud简介

1.1 什么是SpringCloud

在这里插入图片描述
SpringCloud = 分布式微服务架构的一站式解决方案,是多种微服务架构落地技术的集合体,俗称微服务全家桶

SpringCloud这个大集合里有多少种技术

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第二章 学习大纲

在这里插入图片描述

第三章 SpringCloud和SpringBoot之间的依赖关系如何看

https://spring.io/projects/spring-cloud#overview

在这里插入图片描述

第四章 关于Cloud 各种组件的停更/升级/替换

4.1 以前

在这里插入图片描述

4.2 现在

在这里插入图片描述

4.3 SpringCloud 中文文档

https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md

第五章 微服务架构编码构建

5.1 父工程步骤

5.1 new Progect

在这里插入图片描述

5.2 聚合总父工程名称

在这里插入图片描述

5.3 Maven 选版本

在这里插入图片描述

5.4 字符编码

在这里插入图片描述

5.5 注解生效激活

在这里插入图片描述

5.6 java 编译版本选8

在这里插入图片描述

5.7 File Type 过滤

在这里插入图片描述

5.8 父工程pom

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Generated from archetype; please customize.
-->

<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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>cloud2021</artifactId>
    <name>cloud2021 project</name>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>cloud-provider-payment8001</module>
        <module>cloud-consumer-order80</module>
        <module>cloud-api-commons</module>
        <module>cloud-eureka-server-7001</module>
        <module>cloud-eureka-server-7002</module>
        <module>cloud-provider-payment8002</module>
        <module>cloud-provider-payment8004</module>
        <module>cloud-consumerzk-order80</module>
        <module>cloud-providerconsul-payment8006</module>
        <module>cloud-consumerconsul-order80</module>
        <module>cloud-cosumer-feign-order80</module>
        <module>cloud-provider-hystrix-payment8001</module>
        <module>cloud-consumer-feign-hystrix-order80</module>
        <module>cloud-consumer-hystrix-dashboard9001</module>
        <module>cloud-gateway-gateway9527</module>
        <module>cloud-config-center-3344</module>
        <module>cloud-config-client-3355</module>
        <module>cloud-config-client-3366</module>
        <module>cloud-stream-rabbitmq-provider8801</module>
        <module>cloud-stream-rabbitmq-consumer8802</module>
        <module>cloud-stream-rabbitmq-consumer8803</module>
        <module>cloud-alibaba-provider-payment9001</module>
        <module>cloud-alibaba-provider-payment9002</module>
        <module>cloud-alibaba-consumer-nacos-order83</module>
        <module>cloud-alibaba-config-nacos-client3377</module>
        <module>cloud-alibaba-sentinel-service8401</module>
        <module>cloud-alibaba-provider-payment9003</module>
        <module>cloud-alibaba-provider-payment9004</module>
        <module>cloud-alibaba-consumer-nacos-order84</module>
        <module>seata-order-service2001</module>
        <module>seata-storage-service2002</module>
        <module>seata-account-service2003</module>
    </modules>
    <packaging>pom</packaging>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.2.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

5.9 微服务消费者订单order80

5.9.1 pom 文件内容
<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>


    </dependencies>

</project>
5.9.2 RestTemplate配置类
package com.atguigu.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @Author cjz
 * @Date 2022/2/9 21:13
 */

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced   //ribbon 负载均衡一定要加
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
5.9.3 RestTemplate

在这里插入图片描述
在这里插入图片描述

第六章 Eureka 服务注册与发现

6.1 Eureka 基础知识

6.1.1 什么是服务治理

在这里插入图片描述

6.1.2 什么是服务注册

Eureka采用了CS的设计架构,EurekaServer作为服务注册功能的服务器,它是服务法所中心,而系统中的其他微服务,使用Eurka 的客户端连接到Eurka Server并维持心跳链接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。

在注册与发现中,有一个注册中心,当服务启动的时候,会把当前自己服务器的信息比如服务地让通讯地让等以别名方式注册到中心上。另一方(消费者提供者)以别名的方式去注册中心获取到实际的通讯地址,然后再实现本地RPC抵用框架设计思想;在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系,在任何RPC框架中,走回有一个注册中心存放服务地址相关信息。
在这里插入图片描述

6.1.3 Eureka 两组件

Eureka Server 提供服务注册服务

各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到

Eureka Client提供注册中心进行访问

是一个 J ava 客户端,用于简化 Eureka Serve 交互,客户端同时也具备一个内置的、使用轮询( round 一 robin )负载算法的负载均衡器在应用启动后.将会向 Eureka Server 发送心跳(默认周期为 30 秒) . 如果 〔 ureka Server 在多个自叨司期内没有接收到某个节点的心 E urekaserver 将会从服务注册表中把这个服务节点移除(默认 90 秒)

6.2 单机Eureka 构建步骤

6.2.1 cloud-eureka-server7001 servere端

6.2.1.1 pom文件
<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server-7001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

<!--        eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

<!--        自定义API包-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

</project>
6.2.1.2 pom eureka 版本说明

在这里插入图片描述

6.2.1.3 yml 文件
server:
  port: 7001



#集群
#  1、配置映射 127.0.0.1 eureka7001.com
#  2、相互注册,互相守望
eureka:
  instance:
    hostname: eureka7001.com #eureka 服务端的实例名称
  client:
    #false 表示不向注册中心注册自己
    register-with-eureka: false
    #false 便是自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      #设置与eureka server 交互的地址查询服务和注册服务都需要依赖这个地址
#      defaultZone: http://eureka7002.com:7002/eureka/ #集群
       defaultZone: http://eureka7001.com:7001/eureka/  #单机
#  server:
    #关闭自我保护机制,保护不可用服务被即使剔除
#    enable-self-preservation: false
#    eviction-interval-timer-in-ms: 2000
6.2.1.4 主启动
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @Author cjz
 * @Date 2022/2/12 10:12
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}

6.2.2 cloud-provider-payment8001 EurekaClient端

将注册进EurekaServer成为服务提供者provider,类似于尚硅谷学校对外提供授课服务

6.2.2.1 pom文件
<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--        自动检测现有的DataSource-->
        <!--        将创建并注册SqlSessionFactory的实例,该实例使用SqlSessionFactoryBean将该DataSource作为输入进行传递-->
        <!--        将创建并注册从SqlSessionFactory中获取的SqlSessionTemplate的实例。-->
        <!--        自动扫描您的mappers,将它们链接到SqlSessionTemplate并将其注册到Spring上下文,以便将它们注入到您的bean中。-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--        第一个是对数据源的装配,第二个是提供一个JdbcTemplate简化使用,第三个是事务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>
6.2.2.2 yml文件
server:
  port: 8001



spring:
  application:
    name: cloud-payment-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      #采样率值介于 0 到 1 之间 1 则表示全部采集
      probability: 1
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   #当前数据库源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver     #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    druid:
      validationQuery: select 1

eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从EurekaServer 抓取已有的注册信息,默认为true.单节点无所谓,集群必须配置为true才能配置ribbon使用负载均衡
    fetch-registry: true
    service-url:
#      defaultZone: http://localhost:7001/eureka #单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群
  instance:
    #eureka 显示名称
    instance-id: payment8001
    #eureka 显示IP
    prefer-ip-address: true
    #Eureka 客户端向服务端发送心跳的时间间隔 单位为秒(默认30秒)
#    lease-renewal-interval-in-seconds: 1
    #Eureka 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认90秒),超市将剔除服务
#    lease-expiration-duration-in-seconds: 2







mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities   #所有entity别名



6.2.2.3 主启动类
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @Author cjz
 * @Date 2022/2/8 21:50
 */

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



6.2.2.4 测试
  1. 先启动EurekaServer 7001
  2. 再启动8001
  3. http://localhost:7001/

6.2.3 eureka 自我保护机制

Eureka服务端会检查最近15分钟内所有Eureka 实例正常心跳占比,如果低于85%就会触发自我保护机制。触发了保护机制,Eureka将暂时把这些失效的服务保护起来,不让其过期,但这些服务也并不是永远不会过期。Eureka在启动完成后,每隔60秒会检查一次服务健康状态,如果这些被保护起来失效的服务过一段时间后(默认90秒)还是没有恢复,就会把这些服务剔除。如果在此期间服务恢复了并且实例心跳占比高于85%时,就会自动关闭自我保护机制。

为什么会有自我保护机制?

​ Eureka服务端为了防止Eureka客户端本身是可以正常访问的,但是由于网路通信故障等原因,造成Eureka服务端失去于客户端的连接,从而形成的不可用。

6.3 eureka 构建集群

6.3.1 cloud-eureka-server7001

yml文件


#  1、配置映射 127.0.0.1 eureka7001.com
#  2、相互注册,互相守望
server:
  port: 7001
spring:
  application:
    name: cloud-eureka-service
eureka:
  instance:
    # eureka服务端的实例名称
    hostname: eureka7001.com
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/
 

6.3.2 cloud-eureka-server7002

yml文件

server:
  port: 7002
spring:
  application:
    name: cloud-eureka-service2
eureka:
  instance:
    hostname:  eureka7002.com
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

6.3.3 修改映射配置

找到C:\Windows\System32\drivers\etc路径下的hosts文件

添加
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com

刷新
ipconfig /flushdns

6.3.5 支付服务 8001 8002

yml

server:
  port: 8001



spring:
  application:
    name: cloud-payment-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      #采样率值介于 0 到 1 之间 1 则表示全部采集
      probability: 1
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   #当前数据库源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver     #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    druid:
      validationQuery: select 1

eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从EurekaServer 抓取已有的注册信息,默认为true.单节点无所谓,集群必须配置为true才能配置ribbon使用负载均衡
    fetch-registry: true
    service-url:
#      defaultZone: http://localhost:7001/eureka #单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群
  instance:
    #eureka 显示名称
    instance-id: payment8001
    #eureka 显示IP
    prefer-ip-address: true
    #Eureka 客户端向服务端发送心跳的时间间隔 单位为秒(默认30秒)
#    lease-renewal-interval-in-seconds: 1
    #Eureka 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认90秒),超市将剔除服务
#    lease-expiration-duration-in-seconds: 2







mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities   #所有entity别名



6.3.6 订单服务

yml

server:
  port: 80


spring:
  application:
    name: cloud-order-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      #采样率值介于 0 到 1 之间 1 则表示全部采集
      probability: 1

eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从EurekaServer 抓取已有的注册信息,默认为true.单节点无所谓,集群必须配置为true才能配置ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka




6.3.7 @LoadBalanced

ribbon 负载均衡一定要加

6.3.8 测试

在这里插入图片描述

第七章 zookeeper 注册服务与发现

第八章 Consul 注册服务与发现

8.1 什么是Consul

Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorP 公司用 GO 语言开发 ·
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之 C onsul 提供了一种完整服务网格解决方案。

8.2 怎么玩

https://www.springcloud.cc/spring-cloud-consul.html

8.3 安装并运行

https://learn.hashicorp.com/tutorials/consul/get-started-install

8.3 三个注册中心异同点

在这里插入图片描述

第八章 Ribbon 负载均衡调用

8.1 是什么

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们很容易使用Ribbon实现自定义的负载均衡算法。

8.2 Load Balance(负载均衡)

负载均衡:简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡有软件Nginx,LVS,硬件 F5等。

Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别:

Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。
Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。

负载均衡分为集中式负载均衡和进程内负载均衡

集中式LB:即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;
进程内LB:将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

8.3 架构说明

在这里插入图片描述

Ribbon在工作时分成两步
  第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
  第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
  其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

总结:Ribbon其实就是一个软负载均衡的客户端组件,它可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

由于eureka组件中已经包含了Ribbon依赖,所以我们不需要单独引入,当然,单独引入也没有错。

8.3 服务提供者

application.yml:

server:
  port: 8001



spring:
  application:
    name: cloud-payment-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      #采样率值介于 0 到 1 之间 1 则表示全部采集
      probability: 1
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   #当前数据库源操作类型
    driver-class-name: org.gjt.mm.mysql.Driver     #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    druid:
      validationQuery: select 1

eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: true
    # 是否从EurekaServer 抓取已有的注册信息,默认为true.单节点无所谓,集群必须配置为true才能配置ribbon使用负载均衡
    fetch-registry: true
    service-url:
#      defaultZone: http://localhost:7001/eureka #单机版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群
  instance:
    #eureka 显示名称
    instance-id: payment8001
    #eureka 显示IP
    prefer-ip-address: true
    #Eureka 客户端向服务端发送心跳的时间间隔 单位为秒(默认30秒)
#    lease-renewal-interval-in-seconds: 1
    #Eureka 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认90秒),超市将剔除服务
#    lease-expiration-duration-in-seconds: 2







mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities   #所有entity别名



pom文件

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--        自动检测现有的DataSource-->
        <!--        将创建并注册SqlSessionFactory的实例,该实例使用SqlSessionFactoryBean将该DataSource作为输入进行传递-->
        <!--        将创建并注册从SqlSessionFactory中获取的SqlSessionTemplate的实例。-->
        <!--        自动扫描您的mappers,将它们链接到SqlSessionTemplate并将其注册到Spring上下文,以便将它们注入到您的bean中。-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--        第一个是对数据源的装配,第二个是提供一个JdbcTemplate简化使用,第三个是事务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @Author cjz
 * @Date 2022/2/8 21:50
 */

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

8.4 服务消费者

application.yml:

server:
  port: 80

spring:
  application:
    name: cloud-order-service
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
#      defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版

主启动类

@SpringBootApplication
@EnableEurekaClient //代表eureka客户端
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

Bean配置:

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced//使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

8.5 例子链接

https://blog.csdn.net/qq_43753724/article/details/123976933

第九章 OpenFeign 服务接口调用

9.1 OpenFeign概述

9.1.1 OpenFeign 是什么

Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。它的使用方法是定义一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡

9.1.2 OpenFeign 能干什么

Feign旨在使编写Java Http客户端变得更容易。

前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。 所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。

Feign集成了Ribbon

利用Ribbon维护了服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

9.1.3 Feign和OpenFeign两者区别

  1. Feign

Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务

  1. OpenFeign

OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

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

9.2 OpenFeign使用步骤

9.2.1新建80消费模块

在这里插入图片描述

9.2.2 pom文件

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-cosumer-feign-order80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

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

        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

9.2.3 yml文件

server:
  port: 80



eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

  #设置feign 客户端超时时间(Openfeign 默认支持ribbon)
ribbon:
    #指的是建立链接所用的时间 适用于网络正常的情况下,两端链接的时间
  ReadTimeout: 5000
    #指的是建立链接从服务器去读可用资源的时间
  ConnectTimeout: 5000

logging:
  level:
    #feign 日志以什么级别监控那个接口
    com.atguigu.springcloud.service.PaymentFeignService: debug

9.2.4 主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;


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

9.2.5 业务类

业务逻辑接口+@FeignClient配置调用provider服务

新建PaymentFeignService接口并新增注解@FeignClient

package com.atguigu.springcloud.service;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;



@Component
@FeignClient("CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
    @GetMapping("payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping("payment/feign/timeout")
    String paymentFeignTimeOut();
}



在这里插入图片描述

加上@FeignClient注解,该注解的value值就是服务提供者的服务名称。
注意,这个接口的方法不是随便写的,服务提供者提供什么服务这里接口就写什么方法。

控制层Controller:

package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.service.PaymentFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;


@RestController
@Slf4j
public class OrderFeignController {

    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping("/consumer/payment/feign/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id ) {
        return paymentFeignService.getPaymentById(id);
    }

    @GetMapping("/consumer/payment/feign/timeout")
    public String paymentFeignTimeOut() {
        return paymentFeignService.paymentFeignTimeOut();
    }
}

9.2.6 总结

在这里插入图片描述

9.3 OpenFeign超时控制

9.3.1 什么是OpenFeign超时控制?

默认Feign客户端只等待一秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。

在这里插入图片描述

为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。

9.3.2 开启OpenFeign客户端超时控制

YML文件里需要开启OpenFeign客户端超时控制

  #设置feign 客户端超时时间(Openfeign 默认支持ribbon)
ribbon:
    #指的是建立链接所用的时间 适用于网络正常的情况下,两端链接的时间
  ReadTimeout: 5000
    #指的是建立链接从服务器去读可用资源的时间
  ConnectTimeout: 5000

9.4 OpenFeign日志打印功能

9.4.1 是什么?

Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。
说白了就是对Feign接口的调用情况进行监控和输出。

9.4.2 日志级别

  • NONE:默认的,不显示任何日志;
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间;
  • HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
  • FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

9.4.3 配置日志bean

@Configuration
public class FeignConfig
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}

在这里插入图片描述

9.4.4 YML文件里需要开启日志的Feign客户端

server:
  port: 80



eureka:
  client:
    #表示是否将自己注册进EurekaServer 默认为true
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

  #设置feign 客户端超时时间(Openfeign 默认支持ribbon)
ribbon:
    #指的是建立链接所用的时间 适用于网络正常的情况下,两端链接的时间
  ReadTimeout: 5000
    #指的是建立链接从服务器去读可用资源的时间
  ConnectTimeout: 5000

logging:
  level:
    #feign 日志以什么级别监控那个接口
    com.atguigu.springcloud.service.PaymentFeignService: debug

第十章 服务雪崩、服务熔断、服务降级

10.1 服务雪崩

10.1.1 概述

在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。

10.1.2 图解雪崩效应

如存在如下调用链路:

在这里插入图片描述
Service A的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求。此时,如果Service C因为抗不住请求,变得不可用。那么Service B的请求也会阻塞,慢慢耗尽Service B的线程资源,Service B就会变得不可用。紧接着,Service A也会不可用,这一过程如下图所示:

在这里插入图片描述

10.2 服务熔断

10.2.1 概述

熔断器本身是一种开关装置,当某个服务单元发生故障之后,通过断路器(hystrix)的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。

10.3 服务降级

10.3.1 概述

服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的响应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。

简单来说就是关闭微服务系统中某些边缘服务 保证系统核心服务正常运行

10.3.2 服务降级图示:

在这里插入图片描述

10.4 降级和熔断总结

10.4.1 共同点

  • 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
  • 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
  • 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
  • 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;sentinel(阿里巴巴的组件)

10.4.1 异同点

  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
  • 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务边缘服务开始)

熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理

第十一章 Spring Cloud Hystrix

11.1 Hystrix简介

Netflix Hystrix是SOA/微服务架构中提供服务隔离、熔断、降级机制的工具/框架。Netflix Hystrix是断路器的一种实现,用于高微服务架构的可用性,是防止服务出现雪崩的利器。

在分布式架构中,一个应用依赖多个服务是非常常见的。如果其中一个依赖由于延迟过高发生阻塞,调用该服务的线程就会阻塞。如果相关业务的QPS较高,就可能产生大量阻塞,从而导致该应用/服务由于服务器资源被耗尽而拖垮。

11.2 Hystrix基本功能

Hystrix具有隔离(线程池隔离、信号量隔离)服务降级、熔断、限流、缓存等功能,基本上能覆盖到微服务中调用依赖服务会遇到的问题。

11.2.1 隔离

  • 线程池隔离:每个服务对应一个线程池,线程池满了就会进行降级。使用线程池存储当前的请求,线程池对请求做处理,设置任务返回处理超时时间,堆积的请求进入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队列慢慢处理)。

  • 信号量隔离:基于Tomcat线程池来控制,当线程达到某个百分比时将拒绝访问走降级流程。信号量的资源隔离只是起到一个开关的作用,比如服务A的信号量大小为10,就是说它同时只允许有10个Tomcat线程来访问服务A,其他请求都会被拒绝,从而达到资源隔离和限流保护的作用。

11.2.2 限流

限流就是信号量隔离(一般不会使用该模式)

11.2.3 熔断

出发快速失败,保证系统可用性。

11.2.4 降级

使用回调方法返回托底数据。
Hystrix被设计的目标是:对通过第三方客户端访问的依赖项(通常通过网络)的延迟和故障进行保护和控制;在复杂的分布式系统中阻止级联故障;快速失败,快速回复;回退,尽可能优雅地降级;启用类似实时监控、警报和操作的控制。

11.3 Hystrix断路器

11.3.1 Hystrix断路器打开关闭的条件:

  1. 当满足一定的阈值的时候(默认10秒内超过20个请求次数)
  2. 当失败率达到一定的时候(默认10秒内超过50%的请求失败)
  3. 达到以上阈值时断路器将会开启
  4. 当断路器开启的时候,所有请求都不会进行转发。
  5. 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器将会关闭,若失败,继续开启。重复步骤4和5。

11.3.2 断路器流程

在这里插入图片描述

11.4 服务熔断实现

11.4.1 在项目中引入hystrix依赖

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-hystrix-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

<!--        hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

11.4.2 主启动类

package com.atguigu.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;


@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker //代表篇开启Hystrix服务熔断
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class, args);
    }

    /**
     * 此配置是为例服务监控配置,与服务容错本身无关,Springcloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是“hystrix.stream”,
     * 只要在自己的项目里配置上下面的servlet就可以了
     * @return
     */
    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

11.4.3 使用HystrixCommand注解实现断路

//=================服务熔断

    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
            @HystrixProperty(name="circuitBreaker.enabled",value = "true"), //开启断路器
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "10"),//请求次数
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//时间窗日期
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "60"),//失败率达到多少次跳闸

    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id){
        if(id<0){
            throw new RuntimeException("*******id 不能为负数");
        }
        String serialNumber = IdUtil.simpleUUID();

        return Thread.currentThread().getName()+"\t"+"调用成功,流水号"+serialNumber;
    }

    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
        return "*******id 不能为负数,请稍等再试";
    }

上述的fallbackMethod参数用来指定熔断时快速返回的处理方法 commandProperties 配置断路参数

11.5 服务降级的实现

11.5.1 客户端openfeign+hystrix实现服务降级思路

  1. 引入hystrix依赖
<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-feign-hystrix-order80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>


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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>
  1. 配置文件开启feign支持hystrix
feign:
  hystrix:
    enabled: true

  1. 在feign客户端调用加入fallBack指定降级处理

在这里插入图片描述

  1. 开发降级处理方法
package com.atguigu.springcloud.service;

import org.springframework.stereotype.Component;


@Component
public class PaymentFallbackService implements PaymentHystrixService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "----paymentFallbackService fall paymentInfo_OK";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "----paymentFallbackService fall paymentInfo_TimeOut";
    }
}

11.6 服务监控HystrixDashboard

11.6.1 HystrixDashboard概述

除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,对监控内容转化成可视化界面。

11.6.2 新建DashBoard模块

11.6.2.1 pom 文件
<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-hystrix-dashboard9001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>


    </dependencies>

</project>
11.6.2.2 yml文件
 
server:
  port: 9001

11.6.2.2 主启动类
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;


@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardMain9001 {

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

11.6.2.3 所有Provider微服务提供类(8001/8002/8003)都需要监控依赖配置
 <!-- actuator监控信息完善 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

服务提供者都要添加这个依赖

11.6.2.3 启动启动类

访问 http://localhost:9001/hystrix

在这里插入图片描述

11.6.3 断路器演示(服务监控hystrixDashboard)

11.6.3.1 修改提供者端主启动类
@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class PaymentHystrixMain8001
{
    public static void main(String[] args)
    {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }

    /**
     *此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
     *只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

11.6.3.2 9001监控8001

填写监控地址:http://localhost:8001/hystrix.stream

在这里插入图片描述

11.6.3.2 如何看这个Dashboard?

七种颜色代表七种状态

在这里插入图片描述

实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康度从绿色<黄色<橙色<红色递减。该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大该实心圆就越大。所以通过该实心圆的展示,就可以在大量的实例中快速的发现故障实例和高压力实例。

曲线:用来记录2分钟内流量的相对变化,可以通过它来观察到流量的上升和下降趋势。

整图说明:

在这里插入图片描述

第十二章 Spring Cloud Gateway微服务网关

12.1 Gateway网关概述

12.1.1 什么是Gateway?

该项目提供了一个库,用于在 Spring WebFlux 之上构建 API 网关。Spring Cloud Gateway 旨在提供一种简单而有效的方式来路由到 API,并为它们提供横切关注点,例如:安全性、监控/指标和弹性。

SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。

12.1.2 Spring Cloud Gateway 特点

  • 基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 构建
  • 能够匹配任何请求属性的路由。
  • 谓词和过滤器特定于路由。
  • 断路器集成。
  • Spring Cloud Discovery客户端集成
  • 易于编写谓词和过滤器
  • 请求速率限制
  • 路径重写

12.1.3 Spring Cloud Gateway能干什么?

  • 反向代理
  • 鉴权
  • 流量控制
  • 熔断
  • 日志监控
  • 等等

12.1.4 微服务架构中网关在什么位置?

在这里插入图片描述

12.1.5 为什么Gateway使用WebFlux模型?

传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。
但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型异步非阻塞的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring5必须让你使用java8)

Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。

12.2 Gateway三大核心概念

  • Route(路由):构建网关的基本模块,由ID、目标URI、一系列的断言和过滤器组成,如果断言为true就匹配该路由。
  • Predicate(断言):这是一个Java 8 函数谓词。输入类型是Spring FrameworkServerWebExchange。这使您可以匹配来自 HTTP 请求的任何内容,例如请求头或请求参数。如果请求与断言相匹配,就进行路由。
  • Filter(过滤):Spring框架中的GatewayFilter实例通过使用过滤器可以在路由前后对请求进行修改。
    在这里插入图片描述
    web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
    predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了

12.3 Gateway工作流程(重点)

在这里插入图片描述
SpringCloud Gateway的工作机制大概如下:

  1. Gateway接收客户端请求
  2. 客户端请求与路由信息进行匹配,匹配成功被发往相应的下游服务。
  3. 请求经过Filter过滤器链,执行pre(前置过滤器)处理逻辑,如修改请求头信息等。
  4. 请求转被转发志下游服务并返回响应。
  5. 响应经过Filter过滤器链,执行post(后置过滤器)处理逻辑。
  6. 向客户端响应应答。

12.4 入门配置实战

12.4.1 gateway 9527 模块

在这里插入图片描述

12.4.2 pom 文件

 <dependencies>


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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

12.4.3 yml文件

server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

12.4.4 主启动类

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {

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

12.4.5 9527端口的网关如何做路由映射?

我们去cloud-provider-payment8001看看controller的访问地址

在这里插入图片描述
我们现在的需求是:不想暴露8001端口,希望在8001外面套一层9527,只让外界访问网关,让网关统一进行路由的转发。

12.4.6 yml 文件

 
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

12.5 通过微服务名实现动态路由

12.5.1 配置

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

我们启动一个eureka7001,和两个服务提供者payment8001和payment8002,顺便测试下负载均衡(前提是引入了Ribbon)。

新的网关配置文件如下:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。l
b://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri

12.5.1 测试

确保服务都正确启动

在这里插入图片描述
查看服务注册中心:localhost:7001
在这里插入图片描述

12.6 Predicate的使用

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合。

Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 Route。 Spring Cloud Gateway 包含许多内置的Route Predicate Factories。

12.6.1 常用的Route Predicate

After Route Predicate

after 路由谓词工厂采用一个参数,即日期时间。此谓词匹配在指定日期时间之后发生的请求

在这里插入图片描述

Before Route Predicate:before 路由谓词工厂采用一个参数 a datetime。此谓词匹配在指定的 之前发生的请求datetime。

Between Route Predicate:路由谓词工厂之间有两个参数,datetime1和datetime2。此谓词匹配发生在 afterdatetime1和 before的请求datetime2。datetime2参数必须在之后datetime1。

在这里插入图片描述

Cookie Route Predicate:cookie 路由谓词工厂有两个参数,cookie 名称和正则表达式。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。

在这里插入图片描述
Header Route Predicate:标头路由谓词工厂有两个参数,标头名称和正则表达式。此谓词与具有给定名称且值与正则表达式匹配的标头匹配。

在这里插入图片描述

12.7 Filter的使用

12.7.1 Filter是什么?

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。

Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生、

12.7.2 Filter的分类

  • GatewayFilter:Spring Cloud Gateway 包含许多内置的 GatewayFilter 工厂。这个太多了,一般不用。
  • GlobalFilter:全局过滤器。

12.7.3 自定义全局过滤器测试

12.7.3.1实现两个接口:GlobalFilter,Ordered

在这里插入图片描述

12.7.3.2 全局Filter能做什么?
  • 全局日志记录
  • 统一网关鉴权
  • 统一配置所有微服务的跨域
  • 等等
12.7.3.3 案例代码
/**
 * 自定义全局GlobalFilter
 */
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("**********come in MyLogGateWayFilter: "+new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if(uname==null){
            log.info("*******用户名为null,非法用户!!!");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

12.7.3.4 测试

启动

在这里插入图片描述
此时,无法正常使用转发功能。

第十三章 SpringCloud Config分布式配置中心

13.1 SpringCloud Config概述

13.1.1 分布式系统面临的配置问题

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。
SpringCloud提供了ConfigServer来解决这个问题。

13.1.2 SpringCloud Config是什么?

在这里插入图片描述
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。

SpringCloud Config分为服务端和客户端两部分。

服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。

13.1.3 分布式配置中心能做什么?

  • 集中管理配置文件
  • 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release
  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
  • 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
  • 将配置信息以REST接口的形式暴露:post、curl访问刷新均可。

13.1.4 与GitHub或Gitee整合配置

由于SpringCloud Config默认使用Git来存储配置文件(也有其它方式,比如支持SVN和本地文件),但最推荐的还是Git,而且使用的是http/https访问的形式

13.2 Config服务端配置与测试

13.2.1 创建仓库

在这里插入图片描述

13.2.2 新建cloud-config-center-3344模块

它即为Cloud的配置中心模块cloudConfig Center

在这里插入图片描述

13.2.3 pom文件

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-center-3344</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

<!--        添加消息总线mq支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <!--        eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

</project>

13.2.4 yml文件

server:
  port: 3344


spring:
  application:
    name: cloud-config-center #注册到eureka服务器名称
  cloud:
    config:
      server:
        git:
          uri: git@github.com:cjzhub/springcloud-config.git
#          uri: https://github.com/cjzhub/springcloud-config.git #github 上面的git仓库名字
          ignoreLocalSshSettings: true #如果true是,请使用基于属性而不是基于文件的 SSH 配置。
          strict-host-key-checking: true
          #搜索目录
          search-paths:
            - springcloud-config
          private-key: |
                        -----BEGIN RSA PRIVATE KEY-----
                        MIIJKAIBAAKCAgEA1W7UTSQjNxX4n6QYkaXsTJVsGi3fLABknJKs5k4NEM56lhxs
                        acCKhGosX2BW7jMl4Wvcu6XnLXBa0dCud+YWhQiDMOp6B709dKMAKMNeM+k/Ds2p
                        9tM6FGx29vw4TMb7GeoyuVXOKssGXhlD+MI9c5TNePgUPo2veIHOFICnizYQ49k4
                        zMfUHHAvQdVL14MJcyMF1/uPrijU6Mx+W2IOWFDJ116wLTJxayXLwP4zcZkTJ/tu
                        mySTNChwEUGQDamB8+8xmCd1yYttCe+8z+TaEH9Qg2Bu4PcO1fKsQgeBo4aqSxl1
                        SDQTjQdX0vWAXzVEl2HQMhSL2u2VPmjdMvs4Oujw2pmbPKCG2nvaIyEiod2wuJu5
                        3PZWQrlIRZ1uOr+RHs//OTavURlITGmVukaPnLdA6eMOdBA298wqz9nfhCH3io4h
                        7ehwBOCYQcB9W4DxIixINF/Oh5GMix4ay4vRDV2lWNtGdwv39CQFRrZRoWq/ZRRK
                        FLf9wa83/CoQ/0RC4uae4mh7f0w79MDGj9ab0F3LgSvhWQ8aa1cPDmw5JWz2d6NV
                        TzHJ6w6+TQX/vkYNgXa6JFmhfUYAEFwLBQaN7sUaLFltSGbCcx9c2oSEz1e3ZGrk
                        E6O3LzIQw8CQwYsq9DRRrVxMJPjndXMxZiHSdfRSLrHgYdUEktbOQHOH1gECAwEA
                        AQKCAgAXjw48HZsNf41cAb78hLYalfvCwAF8V+bDKaWQHllu23vIigalfa1MhHO1
                        a2rtDBRIV6GbzOpBp78+naxEa89ci93/TkJ+DDN2Zm+kEDybuklNlwIFzrcAfiB7
                        jsegIe6ho6pJruD89EAVrvBDyx0BXxF3ItsJNJaD1MAsny7fPO6MV/PfFsehA/kT
                        aTnf5gTrApioiIoJjVRDBh+EcsRmlzRQY5FKy+CdFSTyfpyrE1x781L4KQdeoIAO
                        R5BhEa7YgDSXOPPVdWBp0l6jC/3OCF+YwNI8XsjycMD24OE8babqdzrs52KpFIBr
                        NtIesECL/S3/+Sie1867ftO7xuMj2brAmNxnJlM8EIsdDIZAnuq8fk+L0TGUGi6b
                        z3zo8gKw0ngCXHeJLDS7wDe1jfHzk1G5aK84MUZr7f+tATLcnEj+uADeONErAPpg
                        CT1kSzSWiWLlcgZ2k0l2Gxcn1Ou5hAamHTb8/KjeYmiX1FWF3LGADvEmCFoWVf8C
                        G2NF95o28uDx0PzLmt/o2vvryBS/WKB4ztCAsDwjQ98XK8BjWubAOjO9HdU2eKvy
                        M5WWexNwrHQ65M6FWI57eshj0qp96x04loiqlaPkOxu7ykQOJODmOeCkbF8qwQ3B
                        debgEzhPIYRk/qVHpTXtDUM9T7u5h/vB/2PzcKnYpnVj49u9qQKCAQEA/tWOXPen
                        DCP9jurnqYHbCkrjqdEerlPuPZTyd69MHzo14jy0A1FYrgcqDO/u4rZ40cUG9CY+
                        K5JW6uEElvEqUdbNLS0T9sUuDxktVzIjGZa8KYK+3OAx7eQw8OqfDsp76UOXHQgu
                        cjmjYGLbcJHlRYHg4uNG1Z7ieT1a8oGyS/S1QZS0TmauNXuEFjfs/MhPIW1R0OqP
                        8/0xBPEo9c3qARSR71FWW41XCiZnCVYLqJzWQx2YBgdT/0/jnwC+bz1B6rU0kVcf
                        BohZoiUkNY8UDP1IDyPmxzbup54tZefxKKlbPnkD6KPJVDNtTS/hajSAEStJ49G6
                        HUeUGI95I3BnIwKCAQEA1mjJdHJSvZCSMWejYW3G2uxCC73G9e3mgSAJ0bVKiG4G
                        QpeHhPn5s7u4qIog+LWgj3GrN6S6py/f7WeydWZTDHGaKtOmJX9jcmTtWyigftHh
                        BZ9aBHS39Qy8QPYIh/DlHykhXhbajhIB8b8TQ5Pqx6AC3jIuuYcwvi1NZzbsVBi4
                        5Ri8S4hf24dVLFWiNrzOQ2GaLtLZN4mIvcF+4Idu1KDiV8tf5zYgcYETy9WTu5gH
                        kbZ5vw/ttvJHcoRGDuq8Xf/Eeh3oUjI/df/ofUDh1Q8TIUIcZ7vOcM7u1l2UOJe8
                        /e6DjKHWEe1aEOdzxGQXTeicXAmZwMCO56X1fGkyiwKCAQBykl88SxfurGu+irx3
                        CGwLl5n96ohJxnBxfXr59nVaANjjC3m/mB4vuAbe5CzZ/0IYxeWXdW40NsofNeXT
                        W0A0pUeADSlRpFtN7HrnHiKLyap1W1QmiCHKm/KpDkNO6hiFyp6xLdF8B4/9sNSK
                        Kv4Snw8V0yswtguKiNxP9aHM5otrncjnCuE+KHc9ag2BpSl2lOjY7eykvOwCFc7d
                        nKOdsrreBwq1hLliVduzZd0+BK2MZUzJQRgxzKBBB5uW9cqiFLA6vBm13S23ac16
                        ywYvxNxV+kUywe7Qq5wrmflh16qvTsdEHAdTdP+qWWGWV15Q2c6Rv+RWb60U0cSb
                        +1hTAoIBAA73q7CMVohTMlFumbIwdqRLv+SP7/a1D9VNxkG0dSqG+7rkVxqKVMse
                        PKrPUbPrAfVhiwFMZ5dKOUiaZ5PYe82vlIKO2ddeSDPxJbyqXmHcBuhckm0jNMBP
                        jki+pCPRRj1hoqmt0L4ANdCJdS/PgKFE405dlHNxI47zHKcq516Lh0S+8E4ZjA+I
                        KAL7S2Kk1YVQp/HC2FUPLdOJUXEdIziGrqZQVTaPyb4Cs74T/8clusmKQn96/i46
                        RZCR+U4LRvEM7MtVkSVDyrhTEAjGYb182uoEcnUvYB7x4yxlxfYZaaEUaGyF06rW
                        teXeMm+wSQwwQ9IM/YW+K3uyUyvHMDcCggEBAJdT02a5D2flZ6/TvjrLrnwQPOQ/
                        CtBw+vsG025CsGVzqbWKm79slvOjt5S/obk8Hv8KKgmwWYsGKazwyDs2CnYIB5Rp
                        QgmWcgiUFC6Jb53h9zuVlvyNeKAJfG5udSRklZ/AySp5Pn+k4cBJdX6LfMxMh9de
                        UyW/aZ3H8XhgjCQmCfmeDBXwzhj+RoOMqnuqjAU91f8ms4d2z8YH5SoLqS4F+mXJ
                        TLOBz5ELS1KO9pKoDNhLULzWENGbfSfVdB9RgjOISf1odD20Lrbr6J4hLYEJhbQ0
                        sQyClUPB2teMwHjbe6y5lK48mKZJrW5wlp6UXyo1WrqwCsMxYp7/Ct6sh9o=
                        -----END RSA PRIVATE KEY-----
      #          username: 17803477500@163.com
#          password: Cjz752020043

      label: master

  #rabbitmq 相关配置 15672是web管理界面端口,5672是MQ访问端口
  rabbitmq:
    host: 192.168.80.131
    port: 5672
    userName: guest
    password: guest




eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#rabbitmq 相关配置 ,暴漏刷新配置端点  curl -X POST http://localhost:3344/actuator/bus-refresh(集体通知)
#定点通知  http://localhost:3344/actuator/bus-refresh/config-client:3355
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'


13.2.5 主启动类

package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @Author cjz
 * @Date 2022/3/7 17:02
 */
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class MainConfigCenter3344 {

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

13.2.6 测试

启动微服务3344

在这里插入图片描述
访问:http://config-3344.com:3344/master/config-dev.yml

在这里插入图片描述

13.2.7 读取配置规则

在这里插入图片描述

  • /{label}/{application}-{profile}.yml

我们访问master分支:

http://config-3344.com:3344/master/config-dev.yml

在这里插入图片描述
http://config-3344.com:3344/master/config-test.yml
在这里插入图片描述
在这里插入图片描述

重要配置细节总结:
label:分支(branch)
name :服务名
profiles:环境(dev/test/prod)

13.3 Config客户端配置与测试

13.3.1 新建cloud-config-client-3355模块

在这里插入图片描述

13.3.2 pom 文件

<?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>cloud2021</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-config-client-3355</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

        <!--        添加消息总线mq支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

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

        <!--        eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

</project>

13.3.3 bootstrap.yml

13.3.3.1 bootstrap.yml是什么?

applicaiton.yml是用户级的资源配置项

bootstrap.yml是系统级的,优先级更加高

Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment。

Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。 Bootstrap context和Application Context有着不同的约定,所以新增了一个bootstrap.yml文件,保证Bootstrap Context和Application Context配置的分离。

要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的,
因为bootstrap.yml是比application.yml先加载的。bootstrap.yml优先级高于application.yml

13.3.3.2 bootstrap.yml内容
server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #config 客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称 上述三个综合: master分支上config-dev.yml的配置我呢见被读取 http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
  rabbitmq:
    host: 192.168.80.131
    port: 5672
    userName: guest
    password: guest

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

13.3.3.3 主启动类
package com.atguigu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @Author cjz
 * @Date 2022/3/7 18:13
 */
@EnableEurekaClient
@SpringBootApplication
public class MainConfigClient3355 {
    public static void main(String[] args) {
        SpringApplication.run(MainConfigClient3355.class,args);
    }
}

13.3.3.4 业务类
package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author cjz
 * @Date 2022/3/7 18:25
 */
@RestController

public class ConfigClientController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo(){
        return configInfo;
    }
}

13.3.3.5 测试

在这里插入图片描述

13.3.3.6 当前配置存在的问题

在这里插入图片描述

13.4 Config客户端之动态刷新

13.4.1 修改3355模块

13.4.1.1 pom引入actuator监控

在这里插入图片描述

13.4.1.2 改yml,暴露监控端口

在这里插入图片描述

13.4.1.4 业务类Controller添加注解@RefreshScope
package com.atguigu.springcloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author cjz
 * @Date 2022/3/7 18:25
 */
@RestController
@RefreshScope  //curl -X POST "http://localhost:3355/actuator/refresh"  避免服务重启
public class ConfigClientController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String getConfigInfo(){
        return configInfo;
    }
}

13.4.2 测试

在这里插入图片描述
  发现版本号已经和远程仓库中的一致了。

到此,成功实现了客户端3355刷新到最新配置内容,避免了服务重启。

13.4.3 还需要改进的地方有哪些?

假如有多个微服务客户端3355/3366/3377等,难道我们每个微服务都要执行一次post请求,手动刷新吗?能否实现消息广播,一次通知,处处生效,别着急,后面我再写一篇SpringCloud Bus消息总线。

第十四章 SpringCloud Bus消息总线

14.1 SpringCloud Bus概述

14.1.1 什么是SpringCloud Bus?

Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。Spring Clud Bus目前支持RabbitMQ和Kafka。

Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。

在这里插入图片描述

14.1.2 Bus能做什么?

Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道。
在这里插入图片描述

14.1.3 为什么被称为总线?

14.1.3.1 什么是总线?

在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。

14.1.3.2 基本原理

ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。

14.2 SpringCloud Bus动态刷新全局广播

14.2.1 新建cloud-config-client-3366,演示广播效果

在这里插入图片描述

pom.xml:

  <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

bootstrap.yml:

 
server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址

#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka

# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

主启动类:

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

Controller:

@RestController
@RefreshScope
public class ConfigClientController
{
    @Value("${server.port}")
    private String serverPort;

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/configInfo")
    public String configInfo()
    {
        return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;
    }
}

14.2.2 设计思想

  1. 利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置

在这里插入图片描述

  1. 利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端的配置
    在这里插入图片描述
    第二种架构方式显然更适合,第一种不适合的原因如下:
  • 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。
  • 破坏了微服务各节点的对等性。
  • 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改

14.2.3 给cloud-config-center-3344配置中心服务端添加消息总线支持

pom:

<!--添加消息总线RabbitMQ支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml:

server:
  port: 3344


spring:
  application:
    name: cloud-config-center #注册到eureka服务器名称
  cloud:
    config:
      server:
        git:
          uri: git@github.com:cjzhub/springcloud-config.git
#          uri: https://github.com/cjzhub/springcloud-config.git #github 上面的git仓库名字
          ignoreLocalSshSettings: true #如果true是,请使用基于属性而不是基于文件的 SSH 配置。
          strict-host-key-checking: true
          #搜索目录
          search-paths:
            - springcloud-config
          private-key: |
                        -----BEGIN RSA PRIVATE KEY-----
                        MIIJKAIBAAKCAgEA1W7UTSQjNxX4n6QYkaXsTJVsGi3fLABknJKs5k4NEM56lhxs
                        acCKhGosX2BW7jMl4Wvcu6XnLXBa0dCud+YWhQiDMOp6B709dKMAKMNeM+k/Ds2p
                        9tM6FGx29vw4TMb7GeoyuVXOKssGXhlD+MI9c5TNePgUPo2veIHOFICnizYQ49k4
                        zMfUHHAvQdVL14MJcyMF1/uPrijU6Mx+W2IOWFDJ116wLTJxayXLwP4zcZkTJ/tu
                        mySTNChwEUGQDamB8+8xmCd1yYttCe+8z+TaEH9Qg2Bu4PcO1fKsQgeBo4aqSxl1
                        SDQTjQdX0vWAXzVEl2HQMhSL2u2VPmjdMvs4Oujw2pmbPKCG2nvaIyEiod2wuJu5
                        3PZWQrlIRZ1uOr+RHs//OTavURlITGmVukaPnLdA6eMOdBA298wqz9nfhCH3io4h
                        7ehwBOCYQcB9W4DxIixINF/Oh5GMix4ay4vRDV2lWNtGdwv39CQFRrZRoWq/ZRRK
                        FLf9wa83/CoQ/0RC4uae4mh7f0w79MDGj9ab0F3LgSvhWQ8aa1cPDmw5JWz2d6NV
                        TzHJ6w6+TQX/vkYNgXa6JFmhfUYAEFwLBQaN7sUaLFltSGbCcx9c2oSEz1e3ZGrk
                        E6O3LzIQw8CQwYsq9DRRrVxMJPjndXMxZiHSdfRSLrHgYdUEktbOQHOH1gECAwEA
                        AQKCAgAXjw48HZsNf41cAb78hLYalfvCwAF8V+bDKaWQHllu23vIigalfa1MhHO1
                        a2rtDBRIV6GbzOpBp78+naxEa89ci93/TkJ+DDN2Zm+kEDybuklNlwIFzrcAfiB7
                        jsegIe6ho6pJruD89EAVrvBDyx0BXxF3ItsJNJaD1MAsny7fPO6MV/PfFsehA/kT
                        aTnf5gTrApioiIoJjVRDBh+EcsRmlzRQY5FKy+CdFSTyfpyrE1x781L4KQdeoIAO
                        R5BhEa7YgDSXOPPVdWBp0l6jC/3OCF+YwNI8XsjycMD24OE8babqdzrs52KpFIBr
                        NtIesECL/S3/+Sie1867ftO7xuMj2brAmNxnJlM8EIsdDIZAnuq8fk+L0TGUGi6b
                        z3zo8gKw0ngCXHeJLDS7wDe1jfHzk1G5aK84MUZr7f+tATLcnEj+uADeONErAPpg
                        CT1kSzSWiWLlcgZ2k0l2Gxcn1Ou5hAamHTb8/KjeYmiX1FWF3LGADvEmCFoWVf8C
                        G2NF95o28uDx0PzLmt/o2vvryBS/WKB4ztCAsDwjQ98XK8BjWubAOjO9HdU2eKvy
                        M5WWexNwrHQ65M6FWI57eshj0qp96x04loiqlaPkOxu7ykQOJODmOeCkbF8qwQ3B
                        debgEzhPIYRk/qVHpTXtDUM9T7u5h/vB/2PzcKnYpnVj49u9qQKCAQEA/tWOXPen
                        DCP9jurnqYHbCkrjqdEerlPuPZTyd69MHzo14jy0A1FYrgcqDO/u4rZ40cUG9CY+
                        K5JW6uEElvEqUdbNLS0T9sUuDxktVzIjGZa8KYK+3OAx7eQw8OqfDsp76UOXHQgu
                        cjmjYGLbcJHlRYHg4uNG1Z7ieT1a8oGyS/S1QZS0TmauNXuEFjfs/MhPIW1R0OqP
                        8/0xBPEo9c3qARSR71FWW41XCiZnCVYLqJzWQx2YBgdT/0/jnwC+bz1B6rU0kVcf
                        BohZoiUkNY8UDP1IDyPmxzbup54tZefxKKlbPnkD6KPJVDNtTS/hajSAEStJ49G6
                        HUeUGI95I3BnIwKCAQEA1mjJdHJSvZCSMWejYW3G2uxCC73G9e3mgSAJ0bVKiG4G
                        QpeHhPn5s7u4qIog+LWgj3GrN6S6py/f7WeydWZTDHGaKtOmJX9jcmTtWyigftHh
                        BZ9aBHS39Qy8QPYIh/DlHykhXhbajhIB8b8TQ5Pqx6AC3jIuuYcwvi1NZzbsVBi4
                        5Ri8S4hf24dVLFWiNrzOQ2GaLtLZN4mIvcF+4Idu1KDiV8tf5zYgcYETy9WTu5gH
                        kbZ5vw/ttvJHcoRGDuq8Xf/Eeh3oUjI/df/ofUDh1Q8TIUIcZ7vOcM7u1l2UOJe8
                        /e6DjKHWEe1aEOdzxGQXTeicXAmZwMCO56X1fGkyiwKCAQBykl88SxfurGu+irx3
                        CGwLl5n96ohJxnBxfXr59nVaANjjC3m/mB4vuAbe5CzZ/0IYxeWXdW40NsofNeXT
                        W0A0pUeADSlRpFtN7HrnHiKLyap1W1QmiCHKm/KpDkNO6hiFyp6xLdF8B4/9sNSK
                        Kv4Snw8V0yswtguKiNxP9aHM5otrncjnCuE+KHc9ag2BpSl2lOjY7eykvOwCFc7d
                        nKOdsrreBwq1hLliVduzZd0+BK2MZUzJQRgxzKBBB5uW9cqiFLA6vBm13S23ac16
                        ywYvxNxV+kUywe7Qq5wrmflh16qvTsdEHAdTdP+qWWGWV15Q2c6Rv+RWb60U0cSb
                        +1hTAoIBAA73q7CMVohTMlFumbIwdqRLv+SP7/a1D9VNxkG0dSqG+7rkVxqKVMse
                        PKrPUbPrAfVhiwFMZ5dKOUiaZ5PYe82vlIKO2ddeSDPxJbyqXmHcBuhckm0jNMBP
                        jki+pCPRRj1hoqmt0L4ANdCJdS/PgKFE405dlHNxI47zHKcq516Lh0S+8E4ZjA+I
                        KAL7S2Kk1YVQp/HC2FUPLdOJUXEdIziGrqZQVTaPyb4Cs74T/8clusmKQn96/i46
                        RZCR+U4LRvEM7MtVkSVDyrhTEAjGYb182uoEcnUvYB7x4yxlxfYZaaEUaGyF06rW
                        teXeMm+wSQwwQ9IM/YW+K3uyUyvHMDcCggEBAJdT02a5D2flZ6/TvjrLrnwQPOQ/
                        CtBw+vsG025CsGVzqbWKm79slvOjt5S/obk8Hv8KKgmwWYsGKazwyDs2CnYIB5Rp
                        QgmWcgiUFC6Jb53h9zuVlvyNeKAJfG5udSRklZ/AySp5Pn+k4cBJdX6LfMxMh9de
                        UyW/aZ3H8XhgjCQmCfmeDBXwzhj+RoOMqnuqjAU91f8ms4d2z8YH5SoLqS4F+mXJ
                        TLOBz5ELS1KO9pKoDNhLULzWENGbfSfVdB9RgjOISf1odD20Lrbr6J4hLYEJhbQ0
                        sQyClUPB2teMwHjbe6y5lK48mKZJrW5wlp6UXyo1WrqwCsMxYp7/Ct6sh9o=
                        -----END RSA PRIVATE KEY-----
      #          username: 17803477500@163.com
#          password: Cjz752020043

      label: master

  #rabbitmq 相关配置 15672是web管理界面端口,5672是MQ访问端口
  rabbitmq:
    host: 192.168.80.131
    port: 5672
    userName: guest
    password: guest




eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#rabbitmq 相关配置 ,暴漏刷新配置端点  curl -X POST http://localhost:3344/actuator/bus-refresh(集体通知)
#定点通知  http://localhost:3344/actuator/bus-refresh/config-client:3355
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'


14.2.4 给cloud-config-client-3355客户端添加消息总线支持

<!--添加消息总线RabbitMQ支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

bootstrap.yml

server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #config 客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称 上述三个综合: master分支上config-dev.yml的配置我呢见被读取 http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
  rabbitmq:
    host: 192.168.80.131
    port: 5672
    userName: guest
    password: guest

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

14.2.5 给cloud-config-client-3366客户端添加消息总线支持

<!--添加消息总线RabbitMQ支持-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

server:
  port: 3366

spring:
  application:
    name: config-client
  cloud:
    #config 客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称 上述三个综合: master分支上config-dev.yml的配置我呢见被读取 http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
  rabbitmq:
    host: 192.168.80.131
    port: 5672
    userName: guest
    password: guest

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"

14.2.6 测试

我们先启动配置后,你再启动两个客户端

在这里插入图片描述
在这里插入图片描述

此时修改远端仓库中的文件版本号,将version改为8

在这里插入图片描述
在这里插入图片描述

14.3 SpringCloud Bus动态刷新定点通知

14.3.1 需求

我们现在的需求是配置更新以后,不想全部通知,只通知3355,不通知3366

其实就是指定具体某一个实例生效而不是全部。

公式:http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}

/bus/refresh请求不再发送到具体的服务实例上,而是发给config server并通过destination参数类指定需要更新配置的服务或实例

14.3.2 案例演示

我们这里以刷新运行在3355端口上的config-client为例,只通知3355,不通知3366

现在修改远程仓库中的配置,将version由8改成9

在这里插入图片描述
只通知3355:curl -X POST “http://localhost:3344/actuator/bus-refresh/config-client:3355”

在这里插入图片描述
发现3366微服务的端口号并没有更新,还是version=8,并没有和远程仓库中version=9保持一致。说明我们定点通知的配置是正确的。

  到此,我们SpringCloud Bus 配合 Springcloud Config 实现配置动态刷新就介绍完了,这里只是讲了点皮毛,更高级的东西需要我们开发过程中去挖掘和提炼。就比如消息队列这块,RabbitMQ 和kafka这都已经是前置只是了。微服务中间件这么多,技术也一直在更新迭代,学起来很容易,但技术是学不完的。如何进行技术选型?项目如何落地实现等等都是我们深入思考的东西。

第十五章 SpringCloud Stream消息驱动

15.1 消息驱动概述

15.1.1 什么是SpringCloud Stream?

官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架。应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream中binder对象交互。通过我们配置来binding(绑定) ,而 Spring Cloud Stream 的 binder对象负责与消息中间件交互。

通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,引用了发布-订阅、消费组、分区的三个核心概念。目前仅支持RabbitMQ、Kafka。

所以,我们只需要搞清楚如何与 Spring Cloud Stream 交互就可以方便使用消息驱动的方式。
一句话:屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。

15.1.2 消息驱动的设计思想

15.1.2.1 标准的MQ

在这里插入图片描述

  • 生产者/消费者之间靠消息媒介传递信息内容
  • 消息必须走特定的通道:消息通道MessageChannel
  • 消息通道里的消息如何被消费呢,谁负责收发处理:消息通道MessageChannel的子接口SubscribableChannel,由MessageHandler消息处理器所订阅
15.1.2.2 为什么用SpringCloud Stream?

  在没有绑定器这个概念的情况下,我们的SpringBoot应用要直接与消息中间件进行信息交互的时候,由于各消息中间件构建的初衷不同,它们的实现细节上会有较大的差异性。通过定义绑定器作为中间层,完美地实现了应用程序与消息中间件细节之间的隔离。通过向应用程序暴露统一的Channel通道,使得应用程序不需要再考虑各种不同的消息中间件实现。

通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。

15.1.2.3 Stream应用编程模型

  应用程序通过inputs或者outputs与Spring Cloud Stream中的binder交互,通过配置来binding,Spring Cloud Stream的binder负责与消息中间件交互,如下图所示。

在这里插入图片描述
  Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件(rabbitmq切换为kafka),使得微服务开发的高度解耦,服务可以关注更多自己的业务流程

  通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。

  Binder层负责和MQ中间件的通信,应用程序Application Core通过inputs接收Binder包装后的Message,相当于是消费者Consumer;通过outputs投递Message给Binder,然后由Binder转换后投递给MQ中间件,相当于是生产者Producer。

Channel描述的是消息从应用程序和Binder之间的流通通道。
Stream中的消息通信方式遵循了发布-订阅模式

15.1.2.4 Spring Cloud Stream标准流程套路

在这里插入图片描述

  • Binder:很方便的连接中间件,屏蔽差异
  • Channel:通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过Channel对队列进行配置。
  • Source和Sink:简单的可理解为参照对象是Spring Cloud Stream自身,从Stream发布消息就是输出,接受消息就是输入。
15.1.2.5 编程API和常用注解
组成 说明
Middleware 中间件,目前只支持RabbitMQ和Kafka
Binder Binder是应用与消息中间件之间的封装,目前实行了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息模型(对应于Kafka的topic,RabbitMQ的exchange),这些都可以通过配置文件来实现。
@Input 注解标识输入通道,通过该输入通道接收到的消息进入应用程序
@Output 注解标识输出通道,发布的消息将通过该通道离开应用程序
@StreamListener 监听队列,用于消费者的队列的消息接收
@EnableBinding 指信道channel和exchange绑定在一起

15.2 案例说明

工程中新建三个子模块

cloud-stream-rabbitmq-provider8801, 作为生产者进行发消息模块

cloud-stream-rabbitmq-consumer8802,作为消息接收模块

cloud-stream-rabbitmq-consumer8803 作为消息接收模块
  
在这里插入图片描述

15.3 消息驱动之生产者搭建

15.3.1 新建cloud-stream-rabbitmq-provider8801模块

在这里插入图片描述

15.3.2 pom.xml

 <dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

15.3.3 application.yml

server:
  port: 8801


spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: #在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: #表示定义的名称 ,用于binding整合
          type: rabbit #消息组件类型
          environment: #设置rabbitmq的相关的配置环境
           spring:
             rabbitmq:
               host: 192.168.80.131
               port: 5672
               username: guest
               password: guest
      bindings: #服务的整合处理
        output: #这个名字是一个通道的名称
          destination: studyExchange #表示要使用的Exchange名称定义
          content-type: application/json #设置消息类型,本次是json,文本则设置 text/plain
          binder: defaultRabbit #设置要绑定的消息服务的具体设置

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  instance:
    lease-renewal-interval-in-seconds: 2 #设置心跳的时间间隔(默认30秒)
    lease-expiration-duration-in-seconds: 5 #如果现在超过了5秒间隔
    instance-id: send-8801.com #在信息列表显示主机名称
    prefer-ip-address: true #访问的路径变为IP地址

15.3.4 主启动类

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

15.3.5 业务类

@EnableBinding(Source.class) //定义消息推送管道
public class IMessageProviderImpl implements IMessageProvider {

    @Resource
    private MessageChannel output; //消息发送管道

    @Override
    public String send() {
        String uuid = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(uuid).build());
        System.out.println("*****uuid" + uuid);
        return null;
    }
}

Controller:

@RestController
public class SendMessageController {

    @Resource
    private IMessageProvider iMessageProvider;

    @GetMapping("/sendMessage")
    public String sendMessage(){
        return iMessageProvider.send();
    }
}

15.3.6 测试

启动服务注册中心模块eureka7001

启动rabbitmq,开启web管理面板:rabbitmq-plugins enable rabbitmq_management

http://localhost:15672/

在这里插入图片描述

启动8001
在这里插入图片描述
访问:http://localhost:8801/sendMessage,多刷新几次之后观察控制台

在这里插入图片描述

15.4 消息驱动之消费者

15.4.1 新建cloud-stream-rabbitmq-consumer8802模块

在这里插入图片描述

15.4.2 pom文件
<dependencies>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

        <!--        S支持全栈式Web开发,包括Tomcat和spring-webmvc。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        使用 spring-boot-starter-actuator 可以用于检测系统的健康情况、当前的Beans、系统的缓存等-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--        Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

15.4.3 application.yml
server:
  port: 8802


spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders: #在此处配置要绑定的rabbitmq的服务信息
        defaultRabbit: #表示定义的名称 ,用于binding整合
          type: rabbit #消息组件类型
          environment: #设置rabbitmq的相关的配置环境
            spring:
              rabbitmq:
                host: 192.168.80.131
                port: 5672
                username: guest
                password: guest
      bindings: #服务的整合处理
        input: #这个名字是一个通道的名称
          destination: studyExchange #表示要使用的Exchange名称定义
          content-type: application/json #设置消息类型,本次是json,文本则设置 text/plain
          binder: defaultRabbit #设置要绑定的消息服务的具体设置
          group: atguiguA

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/
  instance:
    lease-renewal-interval-in-seconds: 2 #设置心跳的时间间隔(默认30秒)
    lease-expiration-duration-in-seconds: 5 #如果现在超过了5秒间隔
    instance-id: receive-8802.com #在信息列表显示主机名称
    prefer-ip-address: true #访问的路径变为IP地址
15.4.4 主启动类
@SpringBootApplication
public class MainStreamConsumer8802 {
    public static void main(String[] args) {
        SpringApplication.run(MainStreamConsumer8802.class, args);
    }

}
15.4.4 业务类
@Component
@EnableBinding({Sink.class})
public class ReceiveMessageListenerController {

    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
        System.out.println("消费者1号,----->接受到的消息: "+message.getPayload()+"\t" + serverPort);
    }
}

测试8801发送消息8802接收消息

启动该模块

访问:http://localhost:8801/sendMessage

在这里插入图片描述

15.5 消息分组与持久化

15.5.1 依照8002,clone一份8003出来

cloud-stream-rabbitmq-consumer8803,该模块配置除了端口号,其他和8002完全一致,不赘述了。

在这里插入图片描述

15.5.2 启动

启动RabbitMQ

启动eureka7001模块

启动provider8801,consumer8002,consumer8003

发送消息之后观察两个消费者的控制台

在这里插入图片描述

15.5.3 消息重复消费案例

比如在如下场景中,订单系统我们做集群部署,都会从RabbitMQ中获取订单信息,那如果一个订单同时被两个服务获取到,那么就会造成数据错误,我们得避免这种情况。这时我们就可以使用Stream中的消息分组来解决。
在这里插入图片描述

注意在Stream中处于同一个group中的多个消费者是竞争关系,就能够保证消息只会被其中一个应用消费一次。
不同组是可以全面消费的(重复消费),同一组内会发生竞争关系,只有其中一个可以消费。

15.5.4 分组
15.5.4.1 分组原理

  微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次。不同的组是可以消费的,同一个组内会发生竞争关系,只有其中一个可以消费。

15.5.4.2 分组原理

8802修改yml

在这里插入图片描述
8803修改yml 同样修改

15.5.4.3 分组之后的测试

重启四个服务

在这里插入图片描述
访问:http://localhost:8801/sendMessage
在这里插入图片描述
在这里插入图片描述
8803并没有收到
在这里插入图片描述
说明同组竞争配置是成功的。

15.5.5 持久化

通过上述,解决了重复消费问题,再看看持久化

停止8802/8803并去除掉8802的分组group: groupA,8803的分组group: groupA没有去掉

8801先发送4条消息到rabbitmq
在这里插入图片描述
先启动8802,无分组属性配置,后台没有打出来消息

在这里插入图片描述
 再启动8803,有分组属性配置,后台打出来了MQ上的消息
在这里插入图片描述

第十六章 SpringCloud Sleuth分布式请求链路跟踪

16.1 Spring Cloud Sleuth概述

16.1.1 为什么会出现这个技术?

  在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个请求最后的失败。

16.1.2 什么是Spring Cloud Sleuth?

  Spring Cloud Sleuth提供了一套完整的服务跟踪的解决方案。

  在分布式系统中提供追踪解决方案并且兼容支持了zipkin。

16.1.3 zipkin是什么?

  Zipkin是一个开源的分布式追踪系统,用于对微服务间的调用链路及逆行监控跟踪。在微服务建构下,用户的一个请求可能涉及多个后台服务间的调用。Zipkin可以追踪(trace)调用链路、收集再各个微服务上所花的时间等信息,并上报到Zipkin服务器。
在这里插入图片描述

  Zipkin UI 还提供了一个依赖关系图,显示有多少跟踪请求通过了每个应用程序。这有助于识别聚合行为,包括错误路径或对已弃用服务的调用。

在这里插入图片描述

16.2 搭建链路监控步骤

16.2.1 zipkin

16.2.1.1 下载jar包

SpringCloud从F版起已不需要自己构建Zipkin Server了,只需调用jar包即可。

zipkin官网地址:https://zipkin.io/pages/quickstart.html

下载完成之后运行Jar

java -jar zipkin-server-2.23.16-exec.jar
16.2.1.2 访问控制台

问控制台:http://localhost:9411/zipkin/

在这里插入图片描述

16.2.1.3 关键术语

  下图所示为一条完整的调用链路,一条链路通过Trace Id唯一标识,Span标识发起的请求信息,各span通过parent id 关联起来

在这里插入图片描述
上图看起来复杂,简单解释如下:

一条链路通过Trace Id唯一标识,Span标识发起的请求信息,各span通过parent id 关联起来
在这里插入图片描述

Trace:类似于树结构的Span集合,表示一条调用链路,存在唯一标识。
span:表示调用链路来源,通俗的理解span就是一次请求信息

16.2.2 服务提供者配置

在cloud-provider-payment8001模块中,

引入依赖:

		<!--包含了sleuth+zipkin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

yml中配置:

在这里插入图片描述
业务类中添加一条测试方法

    /**
     * 链路监控
     *
     * @return
     */
    @GetMapping("zipkin")
    public String paymentZipkin() {
        return "hi,i`am paymentzipkin server fall back.welcome to atguigu.hahahahahhahahah";
    }

16.2.3 服务消费者配置(调用方)

cloud-consumer-order80模块做如下修改:
 pom.xml中引入相关依赖

<!--包含了sleuth+zipkin-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>

application.yml
在这里插入图片描述

业务类添加一条测试方法

//  public static final String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";
// ====================> zipkin+sleuth
    @GetMapping("/consumer/payment/zipkin")
    public String paymentZipkin()
    {
        String result = restTemplate.getForObject(PAYMENT_URL+"/payment/zipkin/", String.class);
        return result;
    }

这里的意思是在cloud-consumer-order80消费者模块中调用cloud-provider-payment8001服务提供者模块中的方法,发生服务调用,我们就可以去zpkin控制台中查看链路调用。

16.2.4 测试

依次启动eureka7001/8001/80
在这里插入图片描述
 访问http://localhost/consumer/payment/zipkin,产生服务调用,多访问几次。
在这里插入图片描述
  查看某一条调用链路
在这里插入图片描述
  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springcloud 笔记 的相关文章

  • sysdba不能远程登录

    sysdba不能远程登录这个也是一个很常见的问题了 碰到这样的问题我们该如何解决呢 我们用sysdba登录的时候 用来管理我们的数据库实例 特别是有时候 服务器不再本台机器 这个就更是有必要了 当我们用sqlplus as sysdba 是
  • 怎么利用数据库做分布式共享锁

    一 适用环境 1 数据库集群模式 1主多从 2 单机数据库 3 数据库必须提供行级锁功能 二 原理 cas算法 代码 更新当前值为new updateCurrentValue id new old old 通过id 查到的值 new 期望的
  • 变量交换的四种方式

    可以使用以下方法对两个变量进行交换 方法一 定义一个中间量 define CRT SECURE NO WARNINGS include

随机推荐

  • VUE 项目文件夹上传下载解决方案

    原理 js将大文件分成多分 全部上传成功之后 调用合并接口合成文件 如果传输中断 下次上传的时候过滤掉已经上传成功的分片 将剩余的分片上传 成功之后合并文件 前置条件 获取uoloadId接口 用于标记分片 分片上传接口 合成文件接口 后端
  • matplotlib画图间隔范围等设置

    import matplotlib pyplot as plt from matplotlib pyplot import MultipleLocator 从pyplot导入MultipleLocator类 这个类用于设置刻度间隔 x va
  • Burpsuite教程(一)Burpsuite 火狐谷歌浏览器抓包教程

    文章目录 Web抓包 火狐抓包 谷歌抓包 小技巧 结束 Web抓包 火狐抓包 环境需求 火狐浏览器 代理插件 1 打开测试工具BurpSuite 默认工具拦截功能是开启的 颜色较深 我们点击取消拦截 下图取消拦截状态 数据包可以自由通过 2
  • vue3.0中全局注册组件版本1-官方

    前言 在对vue3 0的使用和学习中 发现了很多和以前不一样的方法 这里聊一聊vue3 0中给我们提供的全局的注册组件方法 官方文档 入口 目录 具体方法介绍 1 前提 返回一个提供应用上下文的应用实例 应用实例挂载的整个组件树共享同一个上
  • iOS字典转成JSON换行符问题

    问题 使用系统框架将字典转成压缩转义后的JSON字符串 发现字符串中带有多个换行符 系统转JSON的方法如下 let json try JSONSerialization jsonObject with validData options
  • 嵌入式开发笔记—关于>>和<<、&和&&和指针

    1 gt gt 和 lt lt 符号 gt gt 可以理解为除以2的几次方 例如a gt gt b相当于a除以2 b 相反 符号 lt lt 可以理解为乘2的几次方 上面描述的只是它们的数字意义 实际上 gt gt 为右移运算符 其运算规则
  • 架构师之我见

    架构师是一个项目组的灵魂人物 他决定着整个系统的技术选型 整体架构以及模块划分 同时还可能担当与领导层的沟通角色 从某种意义上来说 架构师在很大程度上决定着项目的成败与否 正所谓火车跑得快 全靠车头带 很多优秀的架构师都是从一个优秀的开发人
  • C模拟C++静态断言

    百度百科 C 11新特性 静态断言 Static assertions Static assert 在解释 if 和 error 之后被处理 简单的说就是检测代码 不可能 事件的发生 如果真的发生了 在编译期间编译器会报错 表示代码的逻辑存
  • vector数组最大、小值及所在坐标

    在普通数组中 例 a 1 2 3 4 5 6 int maxValue max element a a 6 最大值 int minValue min element a a 6 最小值 int maxPosition max element
  • 学创客机器人编程材料费贵吗_创客教育只是学编程、机器人和3D打印?

    创客 Mak er 创 指创造 客 指从事某种活动的人 创客 本指勇于创新 努力将自己的创意变为现实的人 这个词译自英文单词 Mak er 源于美国麻省理工学院微观装配实验室的实验课题 此课题以创新为理念 以客户为中心 以个人设计 个人制造
  • cavans 详解

    Canvas Color Styles Shadows 属性 fillStyle 设置或者返回填充的颜色 渐进色 strokeStyle 设置或者返回描边的颜色 渐进色 shadowColor 设置或者返回shadows的颜色 shadow
  • KEIL MDK中 warning: #223-D: function "xxx" declared implicitly 解决方法

    今天在EINT的范例里添加了一个函数 即eint c中添加了一个datawrite 的函数 并在主函数main c中调用 编译便警告 warning 223 D function datawrite declared implicitly
  • 详解Shiro认证流程

    详解Shiro认证流程 isAccessAllowed Subject在如何得到 resolveSession doCreateSubject save Subject subject isAuthenticated onAccessDen
  • EditText TextWatch监听简单使用

    TextWatch 接口方法如下 方法执行顺序 beforeTextChanged gt onTextChanged gt afterTextChanged new TextWatcher This method is called to
  • vue 用户列表,请求接口中数据并渲染页面,分页

    参考 vue电商项目实战 哔哩哔哩 bilibili 用户列表 渲染数据 一般数据 1 接口请求数据格式 get方式 传入参数 page rows 2 初始化定义变量 3 联调接口 1 created 2 methods 发送请求 3 接口
  • VulnHub--Me-and-My-Girlfriend-1

    背景 有两个恋人 即Alice和Bob 这对夫妻本来很浪漫 但是自从Alice在一家私人公司 Ceban Corp 工作以来 爱丽丝对鲍勃的态度发生了一些变化是 隐藏 的 而鲍勃 Bob 寻求您的帮助 以获取爱丽丝 Alice 隐藏的内容并
  • MongoDB用户管理授权

    文章目录 1 角色类型 2 注意事项 3 给单个数据库授权 4 给一个用户授权多个数据库 5 其它命令 1 角色类型 数据库用户角色 read readWrite 数据库管理角色 dbAdmin dbOwner userAdmin 集群管理
  • python监控mysql连接数 批量杀进程 解决too many connections问题

    线上django服务偶尔会因为机器访问mysql过多 造成too many connections 问题 导致服务挂掉 之前调大了最大连接数 有点治标不治本 所以今天抽空写个监控mysql连接数的服务 如果连接数超过某个阈值 就杀掉一部分连
  • Linux防火墙未关闭踩的坑—— No route to host

    网络服务很多时候和Linux防火墙都有着很多的关系 经常因为没有关闭Linux防火墙而导致一些奇葩问题的出现 现有两台服务器 S1 和 S2 在 S1 上部署程序 P1 在 S2 上部署 P2 发现 P1 P2 连接报错 日志只有很简单的
  • springcloud 笔记

    提示 本学习笔记是参照尚硅谷视频写的 视频地址 文章目录 第一章 Spring Cloud简介 1 1 什么是SpringCloud 第二章 学习大纲 第三章 SpringCloud和SpringBoot之间的依赖关系如何看 第四章 关于C