【SpringCloud AlibabaSentinel实现熔断与限流】

news2024/10/5 13:59:48

本笔记内容为尚硅谷SpringCloud AlibabaSentinel部分 

目录

一、Sentinel

1、官网

2、Sentinel是什么

3、下载

4、特性

5、使用

二、安装Sentinel控制台 

1、sentinel组件由2部分构成

2、安装步骤

1.下载

2.运行命令

3.访问sentinel管理界面

三、初始化演示工程

四、流控规则

1、基本介绍

解释说明

2、流控模式

1.直接(默认)

2.关联

3.链路

3、流控效果

1.直接->快速失败(默认的流控处理)

2.预热

3.排队等待 

五、降级规则

1、基本介绍

2、降级策略实战

1.RT

2.异常比例

3.异常数

六、热点key限流

1、基本介绍

2、测试代码

3、配置

4、参数例外项

配置

七、系统规则 

各项配置参数说明 

八、@SentinelResource 

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

2、按照Url地址限流+后续处理 

3、客户自定义限流处理逻辑 

4、更多注解属性说明

九、服务熔断功能 

1、Ribbon系列

2、Feign系列

3、熔断框架比较

十、规则持久化

步骤 


一、Sentinel


1、官网

https://github.com/alibaba/Sentinel

中文:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

2、Sentinel是什么

类似之前学过的Hystrix

3、下载

Releases · alibaba/Sentinel · GitHub

4、特性

5、使用

查看官网:Spring Cloud Alibaba Reference Documentation

服务使用中的各种问题

  • 服务雪崩
  • 服务降级
  • 服务熔断
  • 服务限流

二、安装Sentinel控制台 


1、sentinel组件由2部分构成

后台+前台8080

2、安装步骤

1.下载

Releases · alibaba/Sentinel · GitHub

下载到本地sentinel-dashboard-1.7.0.jar

2.运行命令

前提:java8环境正常,8080端口不能被占用

命令:java -jar sentinel-dashboard-1.7.0.jar

3.访问sentinel管理界面

http://localhost:8080,登录账号密码均为sentinel

三、初始化演示工程


1、启动Nacos8848成功

http://localhost:8848/nacos/#/login

2、Module

cloudalibaba-sentinel-service8401

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

    <artifactId>cloudalibaba-sentinel-service8401</artifactId>



    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringBoot整合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>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </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>

</project>

4、YML

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: '*'

5、主启动

package com.atguigu.springcloud.alibaba;

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

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

6、业务类FlowLimitController

package com.atguigu.springcloud.alibaba.controller;

import com.atguigu.springcloud.alibaba.service.OrderService;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class FlowLimitController
{

    @GetMapping("/testA")
    public String testA()
    {
        return "------testA";
    }

    @GetMapping("/testB")
    public String testB()
    {
        return "------testB";
    }
}

启动Sentinel8080 cmd :java -jar sentinel-dashboard-1.7.0.jar

启动微服务8401

启动8401微服务后查看sentienl控制台,发现什么都没有

Sentinel采用的懒加载说明

执行一次访问即可(http://localhost:8401/testA 和 http://localhost:8401/testB)

效果

结论:sentinel8080正在监控微服务8401

四、流控规则


1、基本介绍

解释说明

2、流控模式

1.直接(默认)

直接->快速失败(系统默认)

配置及说明

2.关联

当关联的资源达到阈值时,就限流自己

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

配置A

postman模拟并发密集访问testB

访问testB成功

postman里新建多线程集合组

将访问地址添加进新新线程组

Run(大批量线程高并发访问B,导致A失效了)

运行后发现testA挂了,点击访问http://localhost:8401/testA,结果Blocked by Sentinel (flow limiting)

3.链路

多个请求调用了同一个微服务(可以想象当作VIP通道)

3、流控效果

1.直接->快速失败(默认的流控处理)

2.预热

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

官网:流量控制 · alibaba/Sentinel Wiki · GitHub

默认coldFactor为3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。

限流 冷启动:限流 冷启动 · alibaba/Sentinel Wiki · GitHub

WarmUp配置

多次点击http://localhost:8401/testB、刚开始不行,后续慢慢OK

应用场景

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

3.排队等待 

官网:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6

测试

五、降级规则


官网:熔断降级 · alibaba/Sentinel Wiki · GitHub

1、基本介绍

RT(平均响应时间,秒级)

      平均响应时间   超出阈值  且   在时间窗口内通过的请求>=5,两个条件同时满足后触发降级

      窗口期过后关闭断路器

      RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXXX才能生效)

 

异常比列(秒级)

    QPS >= 5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级

 

异常数(分钟级)

     异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级

Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。

当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

Sentinel的断路器是没有半开状态的

半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix

2、降级策略实战

1.RT

 

测试

@GetMapping("/testD")
public String testD()
{
    //暂停几秒钟线程
    try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    log.info("testD 测试RT");
    return "------testD";
}

配置

jmeter压测

结论:

永远一秒钟打进来10个线程(大于5个了)调用testD,我们希望200毫秒处理完本次任务,

如果超过200毫秒还没处理完,在未来1秒钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了

后续我停止jmeter,没有这么大的访问量了,断路器关闭(保险丝恢复),微服务恢复OK

2.异常比例

测试

@GetMapping("/testD")
public String testD()
{
    log.info("testD 测试RT");
    int age = 10/0;
    return "------testD";
}

配置

jmeter

结论

3.异常数

异常数是按照分钟统计的

测试

@GetMapping("/testE")
public String testE()
{
    log.info("testE 测试异常比例");
    int age = 10/0;
    return "------testE 测试异常比例";
}

配置

jmeter

六、热点key限流


1、基本介绍

官网:https://github.com/alibaba/Sentinel/wiki/热点参数限流

2、测试代码

@SentinelResource

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1, 

                         @RequestParam(value = "p2",required = false) String p2){
    return "------testHotKey";
}
public String dealHandler_testHotKey(String p1,String p2,BlockException exception)
{
    return "-----dealHandler_testHotKey";
}

3、配置

限流模式只支持QPS模式,固定写死了。(这才叫热点)

@SentinelResource注解的方法参数索引,0代表第一个参数,1代表第二个参数,以此类推

单机阀值以及统计窗口时长表示在此窗口时间超过阀值就限流。

上面的抓图就是第一个参数有值的话,1秒的QPS为1,超过就限流,限流后调用dealHandler_testHotKey支持方法。

测试

4、参数例外项

上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流

配置

 

@SentinelResource

处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;

 

RuntimeException

int age = 10/0,这个是java运行时报出的运行时异常RunTimeException,@SentinelResource不管

总结

 @SentinelResource主管配置出错,运行出错该走异常走异常

七、系统规则 


官网:系统自适应限流 · alibaba/Sentinel Wiki · GitHub

各项配置参数说明 

八、@SentinelResource 


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

启动Nacos成功:http://localhost:8848/nacos/#/login

启动Sentinel成功:java -jar sentinel-dashboard-1.7.0.jar

Module

1.新建cloudalibaba-sentinel-service8401

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

    <artifactId>cloudalibaba-sentinel-service8401</artifactId>


    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringBoot整合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>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </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>

</project>

3.YML

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: '*'

4.业务类RateLimitController

package com.atguigu.springcloud.alibaba.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@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 服务不可用");
    }
}

5.主启动

package com.atguigu.springcloud.alibaba;

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

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

配置流控规则

图形配置和代码关系(表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流)

额外问题:此时关闭问服务8401看看,Sentinel控制台,流控规则消失了-临时(见第十的规则持久化)

2、按照Url地址限流+后续处理 

通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息

业务类RateLimitController

package com.atguigu.springcloud.alibaba.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@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 服务不可用");
    }

    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl()
    {
        return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
    }
}

访问:http://localhost:8401/rateLimit/byUrl

Sentinel控制台配置 

上面兜底方案面临的问题

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

3、客户自定义限流处理逻辑 

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

1.自定义限流处理类CustomerBlockHandler

package com.atguigu.springcloud.alibaba.myhandler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.alibaba.entities.CommonResult;
import org.springframework.stereotype.Component;

public class CustomerBlockHandler
{
    public static CommonResult handleException(BlockException exception){
        return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler");
    }
}

2.RateLimitController

启动微服务后先调用一次http://localhost:8401/rateLimit/customerBlockHandler

3.Sentinel控制台配置 

测试后我们自定义的出来了

4、更多注解属性说明

 

九、服务熔断功能 


sentinel整合ribbon+openFeign+fallback

1、Ribbon系列

1.启动nacos和sentinel

2.提供者9003/9004

新建cloudalibaba-provider-payment9003/9004两个一样的做法

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

    <artifactId>cloudalibaba-provider-payment9003</artifactId>



    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <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>
        <!--日常通用jar包配置-->
        <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>
</project>

YML(记得修改不同的端口号)

server:
  port: 9003

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址

management:
  endpoints:
    web:
      exposure:
        include: '*'

主启动

package com.atguigu.springcloud.alibaba;

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

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

业务类

package com.atguigu.springcloud.alibaba.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    public static HashMap<Long,Payment> hashMap = new HashMap<>();
    static
    {
        hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
    }

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }


}

测试地址:http://localhost:9003/paymentSQL/1

3.消费者84

新建cloudalibaba-consumer-nacos-order84

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

    <artifactId>cloudalibaba-consumer-nacos-order84</artifactId>

    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <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>
        <!--日常通用jar包配置-->
        <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>
</project>

YML

server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719


#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

主启动

package com.atguigu.springcloud.alibaba;

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

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

业务类

ApplicationContextConfig

package com.atguigu.springcloud.alibaba.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;


@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}

CircleBreakerController​

 

fallback和blockHandler都配置

编码

package com.atguigu.springcloud.alibaba.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.concurrent.Executors;

@RestController
@Slf4j
public class CircleBreakerController
{
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
     @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler")
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);
        if (id == 4) {
            throw new IllegalArgumentException ("非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录");
        }
        return result;
    }
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"fallback,无此流水,exception  "+e.getMessage(),payment);
    }
    public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }

}

sentinel需配置

结果 

忽略属性

程序异常打到前台了,对用户不友好 

2、Feign系列

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

    <artifactId>cloudalibaba-consumer-nacos-order84</artifactId>




    <dependencies>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <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>
        <!--日常通用jar包配置-->
        <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>
</project>

3.YML(激活Sentinel对Feign的支持)

server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: '*'
# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true  

4.业务类

带@FeignClient注解的业务接口(定义接口)

package com.atguigu.springcloud.alibaba.service;

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

/**
 * 使用 fallback 方式是无法获取异常信息的,
 * 如果想要获取异常信息,可以使用 fallbackFactory参数
 */
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

fallback = PaymentFallbackService.class(实现类)

package com.atguigu.springcloud.alibaba.service;

import com.atguigu.springcloud.alibaba.entities.CommonResult;
import com.atguigu.springcloud.alibaba.entities.Payment;
import org.springframework.stereotype.Component;

@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
        return new CommonResult<>(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));
    }
}

5.Controller

package com.atguigu.springcloud.alibaba.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
public class CircleBreakerController
{
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    //@SentinelResource(value = "fallback") //没有配置
    //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
    //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
            exceptionsToIgnore = {IllegalArgumentException.class})
    public CommonResult<Payment> fallback(@PathVariable Long id)
    {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }

        return result;
    }
    //本例是fallback
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }

    //==================OpenFeign
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/openfeign/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id)
    {
        if(id == 4)
        {
            throw new RuntimeException("没有该id");
        }
        return paymentService.paymentSQL(id);
    }

}

6.主启动

添加@EnableFeignClients启动Feign的功能

package com.atguigu.springcloud.alibaba;

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

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

3、熔断框架比较

十、规则持久化


一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化

将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

步骤 

1.修改cloudalibaba-sentinel-service8401

2.POM引入持久化依赖

<!--SpringCloud ailibaba sentinel-datasource-nacos -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

3.YML

添加Nacos数据源配置

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        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: '*'

feign:
  sentinel:
    enabled: true # 激活Sentinel对Feign的支持

4.添加Nacos业务规则配置

5.启动8401后刷新sentinel发现业务规则有了

6.快速访问测试接口

7.停止8401再看sentinel

 结束!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/443958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KVM虚拟机的磁盘无损扩容方法-qcow2格式的

起因&#xff1a;我的KVM主机上安装了基于Debian11的 虚拟机母鸡&#xff0c;其他虚拟机都由此克隆而来。因为最初只配置了8G的虚拟硬盘&#xff0c;因此在需要占用比较大的空间的应用时&#xff0c;就比较麻烦。度娘等中文搜索结果没找到答案&#xff0c;只能google了。 这里…

JVM系统优化实践(16):线上GC案例(一)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 列举几个实际使用案例说一下GC的问题。一个高峰期每秒10万QPS的社交APP&#xff0c;个人主页模块是流量最大的那个&#xff0c;而一次个人主页的查询&#xff0c…

python文本自动伪原创-ai一键伪原创

chatgpt批量伪原创的优势 ChatGPT是一个由OpenAI开发的强大的自然语言处理模型&#xff0c;它具有批量伪原创的优势&#xff0c;以下是这些优势&#xff1a; 模型能够处理大量的数据&#xff1a;ChatGPT通过训练大规模的语言模型来生成伪原创文本。这个模型拥有一个庞大的语料…

MySQL:varchar与date类型互转,对接java数据类型String和Date

目录 问题现象&#xff1a; 问题分析&#xff1a; varchar 转 date &#xff1a; date 转 varchar&#xff1a; 解决方法&#xff1a; varchar 转 date &#xff1a; date 转 varchar&#xff1a; 问题现象&#xff1a; 今天在项目中遇到一个问题&#xff1a; 现象&…

将DataTable中的数据保存到Excel (二) 使用NPOI

文章目录 背景1 NPOI 简介2 使用NPOI2.1 创建一个简单的工作簿2.2 简单的读取内容2.3 将DataTable数据导出到Excel(NPOI)2.4 Excel(NPOI)导入到DataTable 3 NPOI 总结 背景 前面写过一篇DataTable导出到Excel的文章&#xff0c;使用的是Office COM组件进行导入导出&#xff0c…

第五章 法律规范

目录 第一节 法律规则 一、法律规范与法律规则的概念辨析二、法律规则的逻辑结构 &#xff08;一&#xff09;假定&#xff1a;&#xff08;二&#xff09;行为模式&#xff1a;&#xff08;三&#xff09;法律后果&#xff1a; 三、法律规则与法律条文的关系 &#xff08;想法…

【vue2】使用vue-admin-template动态添加路由的思路/addRoutes的使用

&#x1f609;博主&#xff1a;初映CY的前说(前端领域) ,&#x1f4d2;本文核心&#xff1a;用原生js实现省市区联动 【前言】在通用的后台管理项目的开发中&#xff0c;不仅仅是会涉及到对表单数据等的增删改查操作还会涉及到一些关于权限管理的问题。我们将基于一个RBAC的思维…

FPGA设计实战演练.高级技巧篇-----读书笔记

第一章 从PCB开始研究FPGA设计问题 一、PCB布线 1、要求 对所有器件进行电源滤波&#xff0c;均匀分配电源&#xff0c;降低系统噪声。 匹配信号线&#xff0c;减小信号反射。 降低并行走线之间的串扰。 减小地反弹效应。 进行阻抗匹配。 2、微带传输布局&#xff0c;走…

全景丨0基础学习VR全景制作,平台篇第六章:全局功能-开场提示

大家好欢迎观看蛙色平台使用教程 编辑器功能位置 1、功能说明 开场提示是指VR漫游作品加载好以后&#xff0c;进入到全景里面时&#xff0c;优先展示的图像。 PC端/移动端&#xff0c;均可设置起到指引用户的作用。 2、功能要用在哪&#xff1f; &#xff08;1&#xff09;场…

无人机影像处理流程

无人机由于其方便快捷&#xff0c;精度高等特点已经广泛应用于农田尺度的作物生长监测。尤其是近年来大疆推出了两个多光谱无人机&#xff0c;价格也相较便宜。但目前无人机的使用实际上需要进一步处理才能获取得到农田的基本信息&#xff0c;主要包括影像的校正和图像拼接&…

FME教程:GIS建筑面转CAD格式JMD,还原房屋建筑结构、层数、地物样式,shp转CAD,GIS转dwg

GIS数据转CAD数据&#xff0c;是经常遇到的需求&#xff0c;但是CAD数据形式与GIS相差甚远&#xff0c;因此GIS转CAD后&#xff0c;要还原图形样式和地物属性便成为了一个难点。 今天介绍使用FME进行shp格式房屋面数据转dwg格式的JMD图层的方法。实现房屋的地物样式、结构、层…

Android studio Activity启动模式

1.四种启动模式&#xff1a; 1&#xff09;.standard&#xff08;标准模式&#xff09; 特点&#xff1a;1.Activity的默认启动模式 2.每启动一个Activity就会在栈顶创建一个新的实例。例如&#xff1a;闹钟程序 缺点&#xff1a;当Activity已经位于栈顶时…

C#模拟实现输出进销存管理系统中的每月销售明细(实验五)

实验五&#xff1a;模拟实现输出进销存管理系统中的每月销售明细 任务要求&#xff1a; 运行程序&#xff0c;输入要查询的月份&#xff0c;如果输入的月份正确&#xff0c;则显示本月商品销售明细&#xff1b;如果输入的月份不存在&#xff0c;则提示“该月没有销售数据或者…

什么是企业数智化的创新加速器?

数智商业创新&#xff0c;使得企业的发展模式有了一个更大的跃升。在数智化转型热潮中&#xff0c;打造数据驱动的智慧企业&#xff0c;实现商业创新与转型升级&#xff0c;构建企业新的竞争优势成为这一阶段企业管理者的核心诉求。围绕这一核心诉求&#xff0c;企业关键要考虑…

javascript通过canvas实现不同时区的时钟绘制

这里使用Javascript的class和canvas技术实现时钟的绘制&#xff0c;并且通过类实例来实现不同时区的时间显示&#xff0c;增强复用性。 如下图&#xff1a; 一、基本知识 在绘制前&#xff0c;我们先熟悉下本次使用到的Canvas相关基础知识&#xff0c;以便后面更好理解并使用。…

Bill Gates 和 Linus Torvalds 同时推崇的编程语言,不可复制的经典

1 缘起 “我们为什么没有这样的东西&#xff1f;&#xff01;” -- Bill Gates 1988年春天&#xff0c;Alan Copper坐在微软的大会议室中&#xff0c;给Bill Gates和微软的十几名员工做了一次著名的演示。 这是个叫做Tripod的开发工具&#xff0c;控制面板上面是一些按钮&…

电视剧是大众文化娱乐的载体,情感、喜剧、悬疑,你钟爱哪种题材?

电视剧作为一种重要的文化娱乐产品&#xff0c;一直以来都受到了人们的热爱和关注。它们通过故事情节、角色塑造、美术设计等方面的表现&#xff0c;向观众展现了生活中的各种情感和经历&#xff0c;同时也传递了一些价值观和思想观念 做为低成本的的娱乐方式&#xff0c;能够为…

1. 数据结构与算法概述

1. 数据结构与算法概述 1.1 什么是数据结构&#xff1f; 官方解释&#xff1a; 数据结构是一门研究非数值计算的程序设计问题中的操作对象&#xff0c;以及他们之间的关系和操作等相关问题的学科。 大白话&#xff1a; 数据结构就是把数据元素按照一定的关系组织起来的集合…

讲真的,我哭死,搞了一个画图软件

文章目录 &#x1f475;回来咯&#x1f474;一起画图吧&#x1f471;画图软件&#x1f47c;项目地址 专栏Python零基础入门篇&#x1f525;Python网络蜘蛛&#x1f525;Python数据分析Django基础入门宝典&#x1f525;小玩意儿&#x1f525;Web前端学习tkinter学习笔记Excel自动…

数据结构——堆和优先队列

文章目录 前言堆堆的引入堆的定义堆的储存结构 优先队列优先队列简介优先队列的基础操作入队出队 优先队列的实现 堆的应用堆排序TOP-K问题什么是TOP-K问题TOP-K问题的排序解法TOP-K问题的堆解法 总结 前言 堆是一个比较基础&#xff0c;且实现起来难度也不算太大的一个数据结…