小言_互联网的博客

Spring Cloud(Alibaba)女朋友看了都会的超详细保姆级笔记!看完还不会算我输!

235人阅读  评论(0)

1. 简介

为什么会出现?

SpringCloud Netflix进入维护模式,意味着不再向模块添加新的功能和组件

能干嘛?

服务降级限流、服务注册与发现、分布式配置管理、消息驱动能力、阿里云对象存储、分布式任务调度




2. Nacos服务注册配置中心

2.1 安装

介绍

Nacos是注册中心+配置中心的组合,即Nacos = Eurake + Config + Bus

下载

https://github.com/alibaba/nacos/releases/download/1.1.4/nacos-server-1.1.4.zip

解压,进入bin目录,双击sartup.cmd启动!访问 http://localhost:8848/nacos:



2.2 Nacos服务注册中心

2.2.1 服务提供者注册

  1. 新建module:cloudalibaba-provider-payment9001

  2. POM

    • 父POM

    • 子POM

          <dependencies>
              <!--SpringCloud ailibaba nacos -->
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</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>
      
      
  3. YML

    server:
      port: 9001
    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #配置Nacos地址
    management:
      endpoints:
        web:
          exposure:
            include: '*'
    
  4. 主启动

    @SpringBootApplication
    @EnableDiscoveryClient
    public class PaymentMain9001 {
         
        public static void main(String[] args) {
         
            SpringApplication.run(PaymentMain9001.class,args);
        }
    }
    
  5. 业务类

    @RestController
    public class PaymentController {
         
    
        @Value("${server.port}")
        private String serverPort;
    
        @GetMapping(value = "/payment/nacos/{id}")
        public String getPayment(@PathVariable("id") Integer id){
         
            return "nacos registry, serverPort: "+serverPort+"\t id: " + id;
        }
    }
    
  6. 新建9002:效果如下:



2.2.2 消费者注册和负载

  1. 新建Module:cloudalibaba-consumer-nacos-order83

  2. POM

    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</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>
    
  3. YML

    server:
      port: 83
    spring:
      application:
        name: nacos-order-consumer
    cloud:
      nacos:
        discovery:
          server-addr: localhost:8848
    #消费者将要去访问的微服务名称(注册成功进nacos,的微服务提供者)
    service-url:
      nacos-user-service: http://nacos-payment-provider
    
  4. 主启动类

    @EnableDiscoveryClient
    @SpringBootApplication
    public class PaymentMain9002 {
         
        public static void main(String[] args) {
         
            SpringApplication.run(PaymentMain9002.class,args);
        }
    }
    
  5. 业务类

    @Configuration
    public class ApplicationContextConfig {
         
        @Bean
        @LoadBalanced
        public RestTemplate getRestTemplete(){
         
            return new RestTemplate();
        }
    }
    
    @RestController@Slf4jpublic class OrderNacosController {
             @Resource    private RestTemplate restTemplate;    @Value("${service-url.nacos-user-service}")    private String serverURL;    @GetMapping(value = "/consumer/payment/nacos/{id}")    public String paymentInfo(@PathVariable("id") Long id){
                 return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);    }}
    
  6. 测试

    http://localhost:83/consumer/payment/nacos/13 实现了负载均衡



2.2.3 服务注册中心对比

Nacos支持AP和CP的切换:




2.3 Nacos配置中心

2.3.1 基础配置

  1. 新建module:cloudalibaba-config-nacos-client3377

  2. POM

     <dependencies>
         <!--nacos-config-->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
         </dependency>
         <!--SpringCloud ailibaba nacos -->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</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>
    
  3. YML
    Nacos同springcloud-config一样,在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动。springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application

    • bootstrap

         #naco配置
         server:
           port: 3377
         spring:
           application:
             name: nacos-config-client
           cloud:
             nacos:
               discovery:
                 server-addr: localhost:8848 #Nacos服务注册中心地址
               config:
                 server-addr: localhost:8848 #Nacos作为配置中心地址
                 file-extension: yaml #指定yamL格式的配置
      
         #  $fspring.application.name}-${spring.profile.active]}.${spring.cLoud.nacos,config.file-extension}
      
    • application

         spring:
           profiles:
             active: dev #表示开发环境
      
  4. 主启动类

     @EnableDiscoveryClient
     @SpringBootApplication
     public class NacosConfigClientMain3377 {
         
         public static void main(String[] args) {
         
             SpringApplication.run(NacosConfigClientMain3377.class,args);
         }
     }
    
  5. 业务类

     @RestController
     @RefreshScope //支持nacos动态刷新
     public class ConfigClientController {
         
         @Value("${config.info}")
         private String configInfo;
    
         @GetMapping("/config/info")
         public String getConfigInfo(){
         
             return configInfo;
         }
     }
    
  6. 在NACOS中添加配置信息

    配置规则:Nacos中的dataid的组成格式及与SpringBoot配置文件中的匹配规则

  7. 自带动态刷新



2.3.2 分类配置

namespace、group、dataid三者关系

默认情况:
Namespace=public,Group=DEFAULT_GROUP,默认Cluster是DEFAULT
Nacos默认的命名空间是public,Namespace主要用来实现隔离。
比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。

Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去

Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。比方说为了容灾,Service微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ),给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。

最后是Instance,就是微服务的实例。

DataId配置方案

  1. 指定spring.profile.active和配置文件的DatalD来使不同环境下读取不同的配置

  2. 默认空间+默认分组+新建dev和test两个dataid,通过spring.profile.active属性就能进行多环境下配置文件的读取,测试:


    想切换哪个环境就换成哪个环境

group分组方案

namespace空间方案



2.4 Nacos集群持久化配置

集群架构说明

  1. 默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。

持久化切换配置

  1. Nacos默认自带的是嵌入式数据库derby

  2. derby到mysql切换配置步骤

    • nacos的conf目录下找到sql脚本:nacos-mysql.sql,在数据库中执行

    • nacos的conf目录下找到application.properties:在最后添加以下内容

       spring.datasource.platform=mysql
      
       db.num=1
       db.url.O=jdbc:mysql://127.0.0.1:3306/nacos_config?
       characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
       db.user=root
       db.password=admin
      
    • 最后进入nacos测试,发布配置文件,发现在数据库中有:



2.5 Nacos的Linux安装

  1. 下载地址:https://github.com/alibaba/nacos/releases/download/1.4.1/nacos-server-1.4.1.tar.gz(1.4.1版本)
  2. 在opt目录中解压即可


2.6 集群配置(上)

  1. 在Linux上Mysql数据库配置,跟在windows上一致,需要新建nacos_config库并生成表

  2. application.properties配置,跟windows上一致

  3. Linux服务器上nacos集群配置cluster.conf

    • 梳理出三台不同nacos集群的服务端口号:3333、4444、5555(cluster.conf)

  4. 编辑nacos的启动脚本startup.sh,使他能够接受不同的启动端口:



2.7 集群配置(下)

测试:启动3333、4444、5555,启动nginx,测试网址:http://192.168.200.130:1111/nacos/#/login,登录密码均为nacos

一定要注意如果访问失败很有可能是端口号没有打开!!!

新建一条配置测试:

微服务cloudalibaba-provider-payment9002注册进nacos集群:

修改配置文件:

    server:
      port: 9002
    spring:
      application:
        name: nacos-payment-provider
      cloud:
        nacos:
          discovery:
            #server-addr: localhost:8848 #配置Nacos地址
            #换成nginx的1111端口,做集群
            server-addr: 192.168.200.130:1111
    management:
      endpoints:
        web:
          exposure:
            include: '*'




3. Sentinel熔断与限流

3.1 简介

是什么

​ 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控
制、熔断降级、系统负载保护等多个维度保护服务的稳定性。一句话,优化版的Hystrix。

特征

  1. 丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突
    发流量控制在系统容量可以承受的范围)、裆息削峰填谷、集群流量控制、实时熔断下游不可用应
    用等。
  2. 完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器
    秒级数据,甚至500台以下规模的集群的汇总运行情况。
  3. 广泛的开源生态:Sentinel提供开箱即用的与其它开源框架/库的整合模块,例如与Spring Cloud.
    Dubbo、gRPC的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入Sentinel,
    完善的SPI扩展点: Sentinel提供简单易用、完善的SPI扩展接口。您可以通过实现扩展接口来快
    速地定制逻辑。例如定制规则管理、适配动态数据源等。



3.2 下载运行

  1. 下载地址:https://github.com/alibaba/Sentinel/releases/download/1.7.0/sentinel-dashboard-1.7.0.jar

  2. sentinel分为两部分:

    • 核心库(Java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo /
      Spring Cloud等框架也有较好的支持。
    • 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用
      容器。
  3. 安装:

    • 在目录下命令行中输入:java -jar .\sentinel-dashboard-1.7.0.jar

    • 输入localhost:8080,进入sentinel页面,用户名密码均为sentinel



3.3 Sentinel初始化监控

新建一个Module:cloudalibaba-sentinel-service8401

  1. POM

     <dependencies>
         <!-- alibaba sentinel -->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-alibaba-sentinel</artifactId>
         </dependency>
    
         <!-- sentinel-datasource-nacos 后续做持久化用到-->
         <dependency>
             <groupId>com.alibaba.csp</groupId>
             <artifactId>sentinel-datasource-nacos</artifactId>
         </dependency>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-openfeign</artifactId>
         </dependency>
         <!--SpringCloud ailibaba nacos -->
         <dependency>
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-starter-alibaba-nacos-discovery</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>
    
  2. YML

     server:
       port: 8401
    
     spring:
       application:
         name: cloudalibaba-sentinel-service
       cloud:
         nacos:
           discovery:
             server-addr: localhost:8848
         sentinel:
           transport:
             #配置sentinel dashboard地址
             dashboard: localhost:8080
             #默认8719端口,假如被占用会自动从8719端口+1,直至找到未被占用的端口
             port: 8719
     management:
       endpoints:
         web:
           exposure:
             include: '*'
    
  3. 主启动

     @EnableDiscoveryClient
     @SpringBootApplication
     public class MainApp8401 {
         
         public static void main(String[] args) {
         
             SpringApplication.run(MainApp8401.class,args);
         }
     }
    
  4. 业务类FlowLimitController

     @RestController
     public class FlowLimitController {
         
         @GetMapping("testA")
         public String testA(){
         
             return "---------testA";
         }
    
         @GetMapping("testB")
         public String testB(){
         
             return "---------testB";
         }
     }
    

启动Sentinel和微服务8401,查看控制台:

Sentinel执行的是懒加载机制,执行一次访问即可!http://localhost:8401/testA或http://localhost:8401/testB:



3.4 流控规则

基本介绍

  1. 资源名∶唯一名称,默认请求路径

  2. 针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)

  3. 阈值类型/单机阈值:

    • QPS(每秒钟的请求数量)︰当调用该api的QPS达到阈值的时候,进行限流
    • 线程数:当调用该api的线程数达到阈值的时候,进行限流
  4. 是否集群:不需要集群

  5. 流控模式:

    • 直接:api达到限流条件时,直接限流
    • 关联:当关联的资源达到阈值时,就限流自己
    • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
  6. 流控效果

    • 快速失败:直接失败,抛异常
    • Warm up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactory,经过预热时长,才达到设置的QPS阈值
    • 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效


3.4.1 流量模式1:直接

QPS直接失败


表示1s内查询超过1次就是失败!

线程数直接失败

QPS:如果超过阈值,其余的请求直接拒绝,御敌于国门之外

线程数直接失败:如果超过阈值,其余的请求无法访问,报错,但是并没有拒绝,关门打狗!



3.4.2 流控模式2:关联

简介

当关联的资源达到阈值时,就限流自己,即当与A关联的资源B达到阀值后,就限流A自己,B惹事,A挂了

Postman模拟并发访问testB:

此时A又挂了:



3.4.3 流控模式3:链路

介绍

多个请求调用了同一个微服务



3.4.4 流控效果1:预热

介绍

  1. 快速失败:默认的流控效果,直接提示失败消息!

  2. 公式:阈值除以coldFactory(默认值为3),经过预热时长以后才会达到阈值!

  3. 默认coldFactory为3,即请求QPS从threshod/3开始,经预热时长逐渐升高设定的QPS阈值

  4. 应用:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放迸来,慢慢的把阀值增长到设置的阀值。



3.4.5 流控效果2:排队等待

介绍

匀速排队,让请求以均匀的速度通过,阀值类型必须设成QPS,否则无效。(漏桶算法)



3.5 降级规则

简介

  1. RT(平均响应时间,秒级)
    平均响应时间超出阈值且在时间窗口内通过的请求>=5,两个条件同时满足后触发降级,窗口期过后关闭断路器,RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)
  2. 异常比列(秒级):QPS >=5且异常比例超过阈值时,触发降级;时间窗口结束后,关闭降级
  3. 异常数(分钟级):异常数超过阈值时,触发降级;时间窗口结束后,关闭降级
  4. Sentinel的断路器是没有半开状态的!


3.5.1 降级策略1:RT



3.5.2 降级策略2:异常比例



3.5.3 降级策略3:异常数

异常数:当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若tiiewindow小于60s,则结束熔断状态后仍可能再进入熔断状态。



3.6 热点规则

介绍

  1. 热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
  2. 自定义服务降级从**@HystrixCommand@SentinelResource**

配置实现

  1. Controller

     @RestController
     public class FlowLimitController {
         
         @GetMapping("/testHotKey")
         @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")     //随便叫啥都可以,只是为了编码的统一和规范和上面一直
         public String testhotKey(@RequestParam(value = "p1",required = false) String p1,
                                  @RequestParam(value = "p1",required = false) String p2){
         
             return "------testHotKey";
         }
    
         public String deal_testHotKey(String p1, String p2, BlockException exception){
         
             return "兜底┭┮﹏┭┮";   //sentinel默认提示为Blocked by sentinel (flow Limiting)
         }
     }
    
  2. 新增热点限流规则:方法testHotkey中的第一个参数只要QPS超过每秒1次,马上降级处理

  3. 测试:

  4. 如果,没有使用兜底方法,即去掉了blockHandler = “deal_testHotKey”,当QPS超过阈值,直接调到ERROR PAGE,对用户不友好!

参数例外项

  1. 在上述的情况下,当p1参数在1s内的QOS超过某个阈值的时候,p1马上就会被限流,现在我们期望,当p1是某个特殊值的时候,它的限流值和平时不太一样,例如当p1值为5的时候,它的阈值可以达到200,这就要用到参数例外项了。

  2. 配置:当p1为5的时候,限流阈值为200,当不为5的时候,限流阈值为1

  3. 当方法中出现异常的时候,无论是否违背热点规则,都无法进行兜底了。

    @SentinelResource处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理,但运行时异常他不管,即它只管配置出错,运行出错该走异常走异常



3.7 系统规则

介绍

  1. 系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU使用率、平均RT、入口
    QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳
    定性。

  2. 系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流星指的是进入
    应用的流量((EntryType.IN ),比如Web服务或Dubbo服务端接收的请求,都属于入口流量。

  3. 系统规则支持以下的模式:

    • Load自适应(仅对Linux/Unixlike机器生效)∶系统的load1作为启发指标,进行自适应系统
      保护。当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触
      发系统保护(BBR 阶段)。系统容量由系统的maxQps * minRt估算得出。设定参考值一般是
      CPu cores* 2.5。
    • CPU usage (1.5.0+版本)︰当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-
      1.0),比较灵敏。
    • 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒。
    • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
    • 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护。
  4. 配置:

    testA、testB每秒QPS大于1的时候,都会直接失败,对整个系统的所有服务都是这样!



3.8 @SentinelResource

按资源名称限流+后续处理

修改8401:

  1. POM:

     <!-- 引入自己定义的api通用包,可以使用payment支付Entity -->
     <dependency>
         <groupId>com.atguigu.springcloud</groupId>
         <artifactId>cloud-api-commons</artifactId>
         <version>${project.version}</version>
     </dependency>
    
  2. 业务类:

     @RestController
     public class RateLimitController {
         
         @GetMapping("/byResource")
         @SentinelResource(value = "byResource",blockHandler = "handleException")
         public CommonResult byResource(){
         
             return new CommonResult(200,"按资源名称限流测试ok",new Payment(2020L,"serial001"));
         }
    
         public CommonResult handleException(BlockException exception){
         
             return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
         }
     }
    
  3. 配置

  4. 问题:关闭8401,sentinel控制台,流控规则消失了!

按url地址限流+后续处理

问题:

  1. 系统默认的,没有体现我们自己的业务要求。
  2. 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观。
  3. 每个业务方法都添加—个兜底的,那代码膨胀加剧。
  4. 全局统—的处理方法没有体现。


3.8.1 自定义限流处理

  1. 创建CustomerBlockHandler类用于自定义限流处理逻辑

     public class CustomerBlockHandler {
         
         public static CommonResult handerException(BlockException exception){
         
             return new CommonResult(4444,"按客户自定义,global handerException ---- 1");
         }
    
         public static CommonResult handerException2(BlockException exception){
         
             return new CommonResult(4444,"按客户自定义,global handerException ---- 2");
         }
     }
    
  2. RateLimitController

        //customerblockhandler
     @GetMapping("/rateLimit/customerBlockHandler")
     @SentinelResource(value = "customerBlockHandler",
             blockHandlerClass = CustomerBlockHandler.class,
             blockHandler = "handerException2")
     public CommonResult customerBlockHandler(){
         
         return new CommonResult(200,"按客户自定义测试ok",new Payment(2020L,"serial003"));
     }
    
  3. 限流后测试:



3.8.2 更多注解说明:

三个核心API:

  1. Sphu定义资源
  2. Trace定义统计
  3. ContextUtil定义上下文


3.9 服务熔断

  1. 新建provider9003、9004,消费者Order84
  2. 实现Sentinel + ribbon + openFeign + fallback

服务熔断无配置

如果程序运行出错,直接404

只配置fallback

程序运行出错,直接调用fallback指定的方法内容返回。

只配置BlockHandler

当程序运行出错,会用BlockHnadler来兜底!

两种都配置

在没被限流降级时,调用fallback,在被限流降级之后,调用blockhandler!

exceptionToIngore

如果这样配置了,就不走fallback了!

熔断框架对比



3.10 Sentinel持久化规则

介绍

一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化,因此将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

步骤

修改8401步骤:

  1. POM

     <dependency>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-datasource-nacos</artifactId>
     </dependency>
    
  2. YML

     server:
       port: 8401
    
     spring:
       application:
         name: cloudalibaba-sentinel-service
       cloud:
         nacos:
           discovery:
             server-addr: localhost:8848
         sentinel:
           transport:
             #配置sentinel dashboard地址
             dashboard: localhost:8080
             #默认8719端口,假如被占用会自动从8719端口+1,直至找到未被占用的端口
             port: 8719
           datasource:
             ds1:
               nacos:
                 server-addr: localhost:8848
                 dataId: cloudalibaba-sentinel-service
                 groupId: DEFAULT_GROUP
                 data-type: json
                 rule-type: flow
    
     management:
       endpoints:
         web:
           exposure:
             include: '*'
    
  3. 新建nacos业务规则配置:

    resource:资源名称;
    limitApp:来源应用;
    grade:阈值类型,0表示线程数,1表示QPS;
    count:单机阈值;
    strategy:流控模式,0表示直接,1表示关联,2表示链路;
    controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
    clusterMode:是否集群。

  4. 启动8401,发现Sentinel控制台有流控规则了!关闭8401,发现流控规则没有了,重启8401并多次刷新,流控规则又回来了!!!!!!!!!




4. Seata处理分布式事务

4.1 分布式事务问题由来

背景

单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证。

总结

一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题!



4.2 Seata

简介

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

分布式事务模型:1个ID+三组件

  1. 1个ID:Transaction ID ------ XID 即全局唯一的事务ID

  2. 三组件概念:

    • Transaction Coordinator (TC):事务协调者,维护全局和分支事务的状态,驱动全局事务提交或回滚。
    • Transaction Manager ™:事务管理器,定义全局事务的范围:开始全局事务、提交或回滚全局事务。
    • Resource Manager(RM):资源管理器,管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
  3. 处理过程:

    1. TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
    2. XID在微服务调用链路的上下文中传播;
    3. RM向TC注册分支事务,将其纳入XID对应全局事务的管辖;
    4. TM向TC发起针对XID的全局提交或回滚决议;
    5. TC调度XID下管辖的全部分支事务完成提交或回滚请求。


4.3 Seata Serve安装

  1. 下载地址:https://github.com/seata/seata/releases/download/v1.0.0/seata-server-1.0.0.zip

  2. 安装:

    • 解压并修改conf目录下的file.conf配置文件!主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息

      • service模块

      • store模块

  3. mysql5.7新建数据库seata

  4. seata里面新建表:建表的db_store.sql在**\seata-server-0.9.0\seata\conf**目录里面

     drop table if exists `global_table`;
     create table `global_table` (
       `xid` varchar(128)  not null,
       `transaction_id` bigint,
       `status` tinyint not null,
       `application_id` varchar(32),
       `transaction_service_group` varchar(32),
       `transaction_name` varchar(128),
       `timeout` int,
       `begin_time` bigint,
       `application_data` varchar(2000),
       `gmt_create` datetime,
       `gmt_modified` datetime,
       primary key (`xid`),
       key `idx_gmt_modified_status` (`gmt_modified`, `status`),
       key `idx_transaction_id` (`transaction_id`)
     );
    
    
     drop table if exists `branch_table`;
     create table `branch_table` (
       `branch_id` bigint not null,
       `xid` varchar(128) not null,
       `transaction_id` bigint ,
       `resource_group_id` varchar(32),
       `resource_id` varchar(256) ,
       `lock_key` varchar(128) ,
       `branch_type` varchar(8) ,
       `status` tinyint,
       `client_id` varchar(64),
       `application_data` varchar(2000),
       `gmt_create` datetime,
       `gmt_modified` datetime,
       primary key (`branch_id`),
       key `idx_xid` (`xid`)
     );
    
    
     drop table if exists `lock_table`;
     create table `lock_table` (
       `row_key` varchar(128) not null,
       `xid` varchar(96),
       `transaction_id` long ,
       `branch_id` long,
       `resource_id` varchar(256) ,
       `table_name` varchar(32) ,
       `pk` varchar(36) ,
       `gmt_create` datetime ,
       `gmt_modified` datetime,
       primary key(`row_key`)
     );
    
  5. 修改seata-server-0.9.0\seata\conf目录下的registry.conf配置文件:指明注册中心为nacos及修改连接信息

  6. 测试:先启动nacos,再启动seata server.bat,成功!

  7. 怎么玩?

    本地@Transactional

    全局@GlobalTransactional

    Seata的分布式交易解决方案:



4.4 Seata原理

AT模式如何做到对业务的无侵入

  1. 一阶段加载:在一阶段,Seata会拦截“业务SQL",

    解析SQL语义,找到“业务SQL"要更新的业务数据,在业务数据被更新前,将其保存成"before image” ,执行“业务SQL"更新业务数据,在业务数据更新之后,其保存成“after image" ,最后生成行锁。
    以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。

  2. 二阶段回滚:即Seata就需要回滚一阶段已经执行的“业务SQL",还原业务数据。回滚方式便是用"before image"还原业务数据;但在还原前要首先要校验脏写,对比”数据库当前业务数据”和"after image",如果两份数据完全一致就说明没有脏写, 可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。

    二阶段提交:因为“业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。


转载:https://blog.csdn.net/lyyrhf/article/details/116333876
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场