SpringCloud笔记

Posted ThinkStu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud笔记相关的知识,希望对你有一定的参考价值。

2023年最新笔记,全文约 3 万字,蕴含 Spring Cloud 常用组件 Nacos、OpenFeign、Seata、Sentinel 等

〇、简介

  1. 什么是Spring Cloud?

    ​ Spring Cloud是一系列框架的有序集合,是一种基于微服务的分布式架构技术。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署,从而提供了良好的开箱即用体验。

  2. 主流的架构方式:

    • 单体架构:架构简单、部署成本低,耦合度高。
    • 分布式架构:架构复杂、部署成本高,耦合度低。
  3. 微服务架构特征:

    总体方向:高内聚、低耦合

    • 单一职责:微服务拆分粒度小,每个服务对应单一业务功能。
    • 面向服务:对外暴露业务接口。
    • 自治:团队独立、技术独立、数据独立、部署独立。
    • 隔离性强:提升容错性、避免出现级联故障。
  4. 常见微服务技术对比:

    • 阿里 Dubbo
    • Spring Cloud(第一代)
    • Spring Cloud Alibaba(第二代)

  5. Spring Cloud 版本说明

大版本说明:

  • 2020 年之前:按照“伦敦地铁”命名,从 A 到 H。
  • 2020 年之后:按年份命名。

小版本说明:

其余版本信息说明

  • snapshot: 快照
  • pre:预览版本
  • alpha : 内测
  • beta : 公测
  • release : 稳定版本
  • GA: General Availability,发行版,即最稳定的版本
  • Final : 正式版
  • Pro(professional) : 专业版
  • Plus: 加强版
  • Retail : 零售版
  • DEMO : 演示版
  • Build : 内部标号
  • Corporation或Enterpraise 企业版
  • M1 M2 M3 : M是milestone的简写 里程碑的意思
  • RC 版本RC:(Release Candidate),几乎就不会加入新的功能了,而主要着重于除错
  • SR : 修正版
  • Trial : 试用版
  • Shareware : 共享版
  • Full : 完全版
  1. Spring Cloud 与 Spring Boot 的选型必须严格按照官方给出的建议去对应,我们可以通过官网或者详情链接https://start.spring.io/actuator/info查看最新推荐的版本对应关系:

  1. 【其他注意点】

    • 微服务之间的联系通过暴露接口实现,比如HTTP协议或者Dubbo协议。
    • 每个微服务都应该有专属的独立数据库,并且每个微服务只能访问自己的数据库,严禁访问别人的微服务数据库(避免重复开发原则)。
  2. 构建 Spring Cloud 工程

    创建 Maven 项目,选择一个较为简单的架构模式(方便后面删除)

将父工程中除了.pom文件的其余文件全部删除

在父工程的pom 文件中修改或新增<packaging>pom</packaging>,代表这是父工程,其他工程项目可继承于它。

<packaging>pom</packaging>

粘贴下列pom配置:

  • <dependencyManagement>只声明依赖,不实现引入,子项目需要显示声明使用的依赖
  • 作用:子项目在声明时可以不用带上版本号,如果子版本中也配置了版本号,则以子版本标明的为主。
  • 注意 Spring Boot 与 Spring Cloud 之间的版本对应关系
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.9.RELEASE</version>
    <relativePath/>
</parent>
<!-- 广泛使用的 lombok -->
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

<!-- 定义版本号 -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
    <mysql.version>5.1.47</mysql.version>
    <mybatis.version>2.1.1</mybatis.version>
</properties>

<dependencyManagement>
    <dependencies>
        <!-- springCloud -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>$spring-cloud.version</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--nacos的管理依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.5.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>$mysql.version</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>$mybatis.version</version>
        </dependency>
    </dependencies>
</dependencyManagement>
  1. 构建 Spring Cloud 工程

    • 方式一:构建初始 Maven 项目(module),后面内容缓慢补充(改 pom、写 yml、编写主启动类、编写业务类)
    • 方式二:构建 Spring Initializr 项目(module),后面改写 pom 文件使形成 Maven 继承关系即可。个人偏向于这种方式
  2. 父类显式声明子类,子类标明继承自父类

<modules>
  <module>子类1</module>
  <module>子类2</module>
</modules>
<!--标明继承自父类-->
<parent>
    <artifactId>springcloud_test</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>
  1. 【强制性】凡是微服务,一般都需要有端口号与名称(程序名称将作为服务Id ,用于与其他服务分辨)

    server:
      port: 8001
    spring:
      application:
        name: payment8001
    
  2. 返回结果定义(通常结构)

    • 数值类型code码,表示状态
    • 消息类型message:例如 success,error 等
    • 消息实体 data,即数据
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CommonResult<T> 
        private Integer code;
        private String message;
        private T data; 
    
    
  3. RestTemplate类简介:

    RestTemplate 是 Spring 提供的用于访问 Restful 风格服务的客户端模版工具集,其提供了多种便捷访问远程 Http 服务的方法,作用类似 Java 原生的 HttpClient

  4. Spring Cloud 初体验:

    服务之间通过暴露接口、HTTP 请求实现沟通。

    自行配置Spring对象 RestTemplate 并注入,发送 GET 与 POST 请求使用 .getForObject().postForObject()

    @Configuration
    public class CommonConfig 
        @Bean
        RestTemplate getRsetTemplate()
            return new RestTemplate();
        
    
    


一、Eureka

NetFlix Eureka,注册中心

  1. 简介:

    • Spring Cloud 使用 Eureka 来充当第一代注册中心,其类似于【发布者】-【订阅者】模型。
  2. Eureka 拥有 3 个角色

    • Eureka Server:服务端。注册中心,提供记录服务信息(业务功能、健康状况等)、心跳监控等。
    • Eureka Client:客户端。用于简化与 Eureka Server 的交互
      • Provider:服务提供者,会将自己的信息注册到 Eureka Server 并每隔 30s 发送一次心跳包。
      • consumer:服务消费者,根据所需从 Eureka Server 中拉取服务列表,并根据负载均衡策略对其中一个微服务发起远程调用。

  3. Eureka 实现原理

    • 微服务启动,会通过 Eureka Client 向 Eureka Server 进行注册自己的信息,而 Eureka Server 会存储该服务的信息。
    • 微服务启动,会周期性地向 Eureka Server 发送心跳(即自身信息,默认周期为30秒),如果Eureka Server在一定时间内没有接收到某个微服务节点的心跳,则会注销该微服务节点(默认90秒)。
    • 每个 Eureka Server 同时也是 Eureka Client ,多个Eureka Server之间通过复制的方式完成服务注册表的同步。
    • Eureka Client 会缓存 Eureka Server 中的信息。即使所有的 Eureka Server 节点宕机,服务消费者依然可以使用缓存中的信息找到服务提供者。

  1. 简单实现(单机版)

    • pom 导包(分为 server 与 client 包,部分Spring版本 parent 中无 Eureka 信息,需手动指定版本)
    • 服务端主配置上开启@EnableEurekaServer
    • yaml 配置 Eureka 信息(注意也要配置 Spring 程序名称)

    【服务端】:服务端一般不需要将自己注册成微服务

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
    @EnableEurekaServer
    
    server:
      port: 10086
    spring:
      application:
        name: MyServer
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka
          # 不向 eureka server 注册自己与获取服务列表
          register-with-eureka: false
          fetch-registry: false 
    

    【客户端】

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    
    spring:
      application:
        name: user_service
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka
    

    ​ 利用 RestTemplate 向其他微服务发送请求。在编写 URL 路径时,通过指定其他微服务的应用名即spring.application.name来调用其服务(如http://userservice/),注册中心将充当 DNS 为各微服务提供解析服务,从而使我们不用像之前一样编写 IP 或域名硬编码的形式(如http://127.0.0.1:8080/)。

    // 子微服务使用其他微服务,并实现负载均衡
    @Bean
    @LoadBalanced
    public RestTemplate rest() 
        return new RestTemplate();
    
    
    String  url="http://userservice/user/"+order.getUserId();
    

二、Ribbon

NetFlix Ribbon,负载均衡

  1. 简介:

    • Ribbon 实现了客户端负载均衡,主要结合 Eureka 用于服务注册及发现。
    • 传统的服务端负载均衡诸如 nginx 需要单独部署额外的服务(成本增加),而 Ribbon 结合 Eureka 可以直接在客户端实现负载均衡。
    • Ribbon拥有多种负载均衡模式,与 nginx 类似。

  2. Ribbon 默认使用【轮询算法】

    下面是 Ribbon 中实现的各种算法简介,IRule是顶层接口,下面是具体的实现类。

  3. 简单实现:

    ​ 由于 Ribbon 与 Eureka 都是由 NetFlix 公司开发,且 Ribbon 常用于与 Eureka 组合实现负载均衡,所以当我们引入 spring-cloud-starter-eureka 依赖时也会默认引入 Ribbon 依赖,无需重复引入。

    <!-- 下面是 spring-cloud-starter-eureka 的依赖 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    

我们要做的只是通过简单配置更改 Ribbon 的【负载均衡】模式,有 2 种办法:

  • 全局生效:因为 Ribbon 的所有模式都基于IRule接口,所以可以通过改变其注入的 Bean 实现。

    @Bean
    public IRule randomRule()
      // 随机模式
      return new RandomRule();	
    
    
  • 局部生效:仅对所调用的某微服务生效

    某微服务名称:
    		ribbon:
    			NFLoadBalancerRuLeClassName: com.netfLix.Loadbalancer.RandomRule
    

    微服务名称即:所要调用的微服务名称

另外,由于 Ribbon 默认采用**【懒汉模式】,即第一次请求链接时才会获取“可用的微服务列表”,这将造成一定的体验损耗,我们可以将其更改成【饿汉模式】**。

ribbon:
	eager-load:
		enable: true
		# 客户端在启动时,就会去请求这些名称的“微服务表”
		clients:
			- userservice
			- vipservice

三、Nacos

阿里 Nacos,Eureka的替代品

注册中心(服务发现中心)、配置管理。

0、简介

  1. Nacos /nɑ:kəʊs/Dynamic Naming and Configuration Service(动态域名命名和配置服务)首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,Nacos 致力于发现、配置和管理微服务。

  2. Nacos 使用 Java 编写,如果本地 JDK 环境配置不对,会出现一系列不明所以的报错。

  3. Nacos是一个内部微服务组件,需要在可信的内部网络中运行,并非面向公网环境的产品,不可暴露在公网环境,强烈不建议部署在公共网络环境。Nacos提供了简单的鉴权实现,是为防止业务错用的弱鉴权体系,而不是防止恶意攻击的强鉴权体系。

  1. Nacos 架构

    • Namespace:命名空间,默认空串代表公共命名空间public
    • Group:分组,默认为DEFAULT_GROUP,作项目区分,用来区分相同开发环境下的不同项目(如测试环境下的电商项目、测试环境下的培训机构项目)
    • Service:服务,提供具体服务(如登录服务、验证码服务等)。
    • Cluster:集群,如上海集群,杭州集群。

    例如在某命名空间下(如测试环境的命名空间),有众多分组(项目),每个项目又有一些服务(服务可以说是最小可用单位),服务又会归属于不同集群(提升可用性与性能)。

  1. 整合 Spring Cloud 配置说明:

    • discovery :服务发现中心
    • config:配置中心

  1. 当 Nacos 没有整合 OpenFeign 时,默认使用的是 RestTemplate ,此时如果需要实现“负载均衡”策略,则:

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() 
        return new RestTemplate();
    
    

    负载均衡方式默认为轮询

1、安装

  1. 简介:

    • Nacos 已经被封装成 jar 包,我们配置好基本要求,直接运行 jar 包即可。
    • 在程序运行之后,其余配置只能在网页端的控制面板修改,不能在代码中修改。
  2. 手动模式

    • GitHub下载

    • 解压并启动(此处为单机模式)

      • 单机模式

      • 集群模式

    # 单击模式启动
    ./startup.sh -m standalone
    # 关闭
    ./shutdown.sh
    
  3. Docker模式

    挂载配置目录与日志目录

    docker run \\
    --name myNacos \\
    -e MODE=standalone \\
    --env NACOS_AUTH_ENABLE=true \\
    -p 8848:8848 \\
    -d \\
    nacos/nacos-server
    

    挂载已有的配置目录与日志目录:提前将 Nacos/conf/目录文件拷贝至/tmp/nacos/conf/

    docker run \\
    --name myNacos \\
    -e MODE=standalone \\
    --env NACOS_AUTH_ENABLE=true \\
    -v /tmp/nacos/conf/:/home/nacos/conf/ \\
    -v /tmp/nacos/logs/:/home/nacos/logs/ \\
    -p 8848:8848 \\
    -d \\
    nacos/nacos-server
    

    挂载新的的配置目录与日志目录:

    docker run \\
    --name myNacos \\
    -e MODE=standalone \\
    --env NACOS_AUTH_ENABLE=true \\
    -v nacosConf:/home/nacos/conf/ \\
    -v nacosLogs:/home/nacos/logs/ \\
    -p 8848:8848 \\
    -d \\
    nacos/nacos-server
    
    docker inspect mq | grep volume
    
  4. 开启服务器鉴权

    按照官方文档配置启动,默认是不需要登录的,这样会导致配置中心对外直接暴露。而启用鉴权之后,需要在使用用户名和密码登录之后,才能正常使用nacos。(所以 Nacos 才推荐不要把自身放在“外网”中)

    配置/conf/application.properties文件

    nacos.core.auth.enabled=true
    

    如此一来,Client 端便需要配置 nacos 的账号密码才能登录。

    **注意:**鉴权开关是修改之后立马生效的,不需要重启服务端。

  5. 安装之后

    • 可以通过查看/logs/start.out日志来查看启动详情。
    • 访问http://127.0.0.1:8848/nacos登录 Nacos,默认账号密码均为 nacos。
  6. Spring项目引入 Nacos 依赖

    父工程(这是必备的)

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

    子工程

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
  7. 配置 Nacos 地址

    在未开启“鉴权模式”时,可以不配置usernamepassword

    spring:
      cloud:
        nacos:
          server-addr: localhost:8848
          username: nacos
          password: nacos
    
  8. **注意:**Nacos 包不可与 Eureka 包同时导入同一工程,否则产生冲突Bean multiple

2、命名空间

命名空间使实例之间【相互隔离】,看不到彼此,这可以用作正式环境与测试环境的区分。当 Nacos 启动时会默认使用全局唯一命名空间public

步骤:

  • 新建命名空间(此处自动使用 UUID 当作“主键id”)
  • 实例 yml 文件配置命名空间(使用生成的主键 id )

spring:
	cloud:
    nacos:
      server-addr: http://localhost:8848
      discovery:
        cluster-name: HZ
        namespace: 53a68426-7e6c-4e09-83e3-57a87f116980		# 声明命名空间

3、服务分级模型

服务分级模型在相同“命名空间”的前提下,Nacos 利用服务分级存储模型来提高【容灾率】,例如:

  • 总体服务
    • 集群(如上海、杭州)
      • 实例

集群默认为DEFAULT_GROUP,更改如下:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ  # 例如:HZ代表杭州、SH表示上海
  • 一个集群就相当于一个小型完善的“生态系统”。
  • 在开启集群设置后,我们应该将**【负载均衡策略】修改为【优先使用本地集群】(如果本地集群全部失效,程序会自动转向其他集群发起请求),随后 Nacos 就会再在本地集群选择【随机选取】**的方式进行实例的选择(注意这里不是轮询)。
某微服务名称:
  ribbon:
    NFLoadBalancerRuLeClassName: com.alibaba.cloud.ribbon.NacosRule

4、服务权重

​ Nacos可以通过【网页控制台】为实例设置权重,范围从0~1,值越大越容易被访问,设置为0则完全不会被访问,这可以用作“灰度升级”。

注意:必须是相同集群下拥有多个相同实例时,才可配置权重。

5、服务监测

监测实例的健康状态

Nacos拥有临时监测(被动)、非临时监测(主动)

Eureka只有临时监测

  1. 临时监测(默认、被动检测)

    • 发送心跳包。
    • 客户端心跳上报Nacos实例健康状态,默认间隔5秒,Nacos在15秒内未收到该实例的心跳,则会设置为不健康状态,超过30秒则将实例移除。在被移除后如果又开始上报心跳,则会重新注册实例。
    • 运维只能通过检查实例数量来监测实例状态,但临时实例的设置本就是应对“流量突增”情况的。
  2. 非临时监测(主动检测)

    • Nacos会定期 主动 发起请求询问实例的健康状态(不发送心跳包)
    • 在实例失效时也会主动 push 推送信息给服务消费者,及时更新数据。此时实例并不会被移除,依旧保留在服务列表,只是状态为false
    • 主动询问的方式对服务器压力较大,它的好处是运维可以实时看到实例的健康状态,便于后续的警告、扩容等一些列措施。
  3. 配置非临时检测:

    spriing:
    	cloud:
        nacos:
          server-addr: http://localhost:8848
          discovery:
            cluster-name: HZ 
            namespace: 53a68426-7e6c-4e09-83e3-57a87f116980
            # ephemeral,短暂的
            ephemeral: fasle		
    
  4. 【非临时监测】的另外一个作用:设置保护阈值,防止产生服务雪崩效应

    Nacos中可以针对具体的实例设置一个保护阈值,值为0-1之间的浮点类型。本质上,保护阈值是⼀个⽐例值(当前服务健康实例数/当前服务总实例数)。

    ⼀般情况下(临时监测),服务消费者要从Nacos获取可用实例有健康/不健康状态之分。Nacos在返回实例时,只会返回健康实例。

    但在高并发、大流量场景会存在⼀定的问题。比如,服务A有100个实例,98个实例都处于不健康状态,如果Nacos只返回这两个健康实例的话,流量洪峰的到来可能会直接打垮这两个服务,进一步产生雪崩效应。保护阈值存在的意义在于当服务A健康实例数/总实例数 < 保护阈值时,说明健康的实例不多了,保护阈值会被触发(状态true)。

    Nacos会把该服务所有的实例信息(健康的+不健康的)全部提供给消费者,消费者可能访问到不健康的实例,请求失败,但这样也⽐造成雪崩要好。牺牲了⼀些请求(将请求分流到不健康的实例),保证了整个系统的可⽤。

6、配置管理

实现“统一配置”与“热更新”

  1. 简介:

    使用 Nacos 可以实现实例的统一配置与配置热更新(即当配置被修改时,主动推送并实现热更新、不重启)

    应该将固定不变配置写入服务本身的application.yml,易于变化的配置则写入 Nacos 配置文件。

  2. 应用 Nacos 统一配置流程图

    声明:一个服务如果以 nacos 作为配置中心,应该先拉取 nacos 中管理的配置,然后与本地的配置文件比如 application.yml 中的配置合并,最后作为项目的完整配置,启动项目。

    实现原理:Spring 中bootstrap.yml文件的启动优先级高于application.yml,我们可以将 Nacos 配置写入其中(注意单词有两个t)。

  3. 【共同配置】

    在Nacos情境下,微服务在启动时会从 Nacos 读取2个配置文件,按优先级为:

    • 配置名称-环境.yamluserservice-dev.yaml
    • 配置环境.yamluserservice.yaml

    而且无论如何都会读取到第二个配置环境,所以我们可以将微服务相同的配置再放入第二种配置环境中。

  4. 【统一配置】

    • Nacos 中新建配置文件,命名规则:服务名称-环境.yaml,在其中编写易于变化的配置。
    • 微服务程序中引入nacos-config依赖。
    • 编写bootstrap.yml文件,这些配置决定了微程序会去读取哪一个Nacos配置文件。
      • Nacos地址
      • 服务名称
      • 当前环境
      • 文件后缀名

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-configSpringCloud入门概述

Spring Cloud资料

[Spring Cloud]Eureka+OpenFeign

Spring Cloud 简介

[转帖]Spring Cloud底层原理

SpringCloud学习分布式配置中心(Spring Cloud Config)(Finchley版本)