SpringCloud Sentinel 学习笔记

Sentinel 教程学习笔记

1. Sentinel 介绍

1.1 Sentinel 的组成

核心库(Java 客户端): 不依赖任何框架 / 库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持;

控制台(Dashboard): 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器;

1.2. Sentinel 的特征

丰富的应用场景: Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷(对于突然到来的大量请求,您可以配置流控规则,以稳定的速度逐步处理这些请求,从而避免流量突刺造成系统负载过高)、集群流量控制、实时熔断下游不可用应用等;

完备的实时监控: Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况;

广泛的开源生态: Sentinel 提供开箱即用的与其它开源框架 / 库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel;

完善的 SPI 扩展点: Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等;

1.3. 相关概念

资源 资源是Sentinel的关键概念,它可以是Java应用程序中的任何内容,比如程序提供的服务,或者是一段代码。只要通过Sentinel API定义的代码,就是资源,能够被Sentinel保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来表示资源。

规则 规则是指围绕着资源的实时状态设定的规则,它可以包括流量控制规则、熔断降级规则以及保护规则。所有规则可以动态实时调整。

流量控制:根据系统的处理能力对流量进行控制,处理不了的请求直接丢弃;

熔断降级:如果某个资源不稳定,最终会导致请求发生堆积,在微服务系统中进而导致级联错误,熔断机制可以应对这种问题,对资源进行控制,让请求快速失败,避免影响其他的资源而产生级联故障;当资源被降级后,在接下来的降级时间窗口内,对该资源的调用都会自动熔断(默认行为是抛出DegradeException);

2. Sentinel 初体验

使用SpringBoot工程,通过Sentinel的API来体验一把资源的限流保护;下面的代码是通过在代码中定义限流规则的,在介绍到Sentinel控制台后,我们就可以在控制里动态的设置限流规则;

2.1 限流规则体验

2.1.1 修改pom.xml添加依赖

<!--添加Sentinel依赖-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-core</artifactId>
            <version>1.7.2</version>
        </dependency>

2.1.2 定义一个Controle来测试CentinelAPI

关键点

  • SphU.entry 来定义限流入口,并定义资源名称;
  • 使用@PostConstruct注解在构造方法执行后,添加自定义的限流规则;
  • BlockException 限流规则被触发后抛出的异常;
package com.linwei.sentinel.control;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: linwei
 * @date: 2021/7/15 22:41
 * @Description:
 */

@RestController
public class TestContorl {

    @GetMapping("/hello")
    public String hello(){
        try (Entry entry = SphU.entry("Hello")){ //限流入口
            return "Hello Sentinel!";  //这里就是被保护的资源
        }catch (BlockException ex){
            ex.printStackTrace();
            return "系统繁忙,稍后重试!";  //限流规则触发后的操作
        }

    }

    // 定义限流规则
    // @PostConstruct 该注解的作用是在当前类的构造原函数执行之后执行的方法
    @PostConstruct
    public void initFlowRules(){
        //1. 创建存放限流规则的集合
        List<FlowRule> rules = new ArrayList<>();
        //2. 创建限流规则
        FlowRule rule1 = new FlowRule();
        // 定义资源
        rule1.setResource("Hello");
        // 定义限流规则类型
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置QPS的限流值
        rule1.setCount(2);

        //3. 将限流规则存放到集合中
        rules.add(rule1);
        //4. 加载限流规则
        FlowRuleManager.loadRules(rules);

    }
}

2.1.3 测试限流效果

我们在代码里设置的限流规则是每秒处理两个QPS,因此当我们在浏览器频繁刷新请求/hello 时,就会触发限流规则;

浏览器显示如下:

Hello Sentinel!
系统繁忙,稍后重试!

2.2 熔断降级体验

熔断降级会在调用链路中,某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源导致级联错误。当资源被降级后,在接下来的降级时间窗口内,对该资源的调用都会自动熔断(默认行为是抛出DegradeException);

熔断降级的规则设置有两种方式:

  • 本地代码设置;
  • 在Sentinel控制台动态设置;

以下以本地代码为例进行演示:

2.2.1 添加依赖;

这一步跟上面的2.1.1是一样的,已经添加过依赖,这一步就可以跳过;

2.2.2 在controller中定义资源

下面是使用了注解的方式定义资源;

@RestController
public class TestController {

    // Sentinel 注解方式定义资源;  限流控制
    @GetMapping("ann-test")
    @SentinelResource(value="sentinel-ann",blockHandler = "exceptionHandler")
    public String annotionTest(){
        return "hello sentinel annotation";
    }

    // blockHandler函数
    public String exceptionHandler(BlockException ex){
        ex.printStackTrace();
        return "系统繁忙,请稍后";
    }


    // Sentinel 注解方式定义资源  熔断控制
    @SentinelResource(value = "sentinel-deg",fallback = "exceptionHandler2")
    @RequestMapping("/deg-test")
    public String degradeTest(){
        return "hello sentinel degrade test!";
    }

    //降级方法
    public String exceptionHandler2(){
        return "触发熔断降级,系统繁忙,请稍后";
    }

}

2.2.3 在controller定义熔断规则

我们继续在上面的代码里,用代码的方式进行定义熔断规则,使用sentinel控制台后,这个步骤就不用要了,只需要上面定义好资源后,在控制台去定义规则即可;

    // 定义熔断规则
    // @PostConstruct 该注解的作用是在当前类的构造原函数执行之后执行的方法
    @PostConstruct
    public void initFlowRules(){
        //1. 创建存放限流规则的集合
        List<DegradeRule> rules = new ArrayList<>();
        //2. 创建限流规则
        DegradeRule rule = new DegradeRule();
        // 定义资源
        rule.setResource("sentinel-deg");
        // 定义限流规则类型:熔断降级(秒级RT)类型
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        // 设置阈值
        rule.setCount(0.01);
        // 降级的时间窗口,单位为s
		rule.setTimeWindow(10);
        //3. 将限流规则存放到集合中
        rules.add(rule);
        //4. 加载限流规则
        DegradeRuleManager.loadRules(rules);

    }

在浏览器方式http://localhost:8080/deg-test,慢速刷新可以正常返回,快速刷新几次后,出现触发熔断降级,系统繁忙,请稍后 ,并且之后再次刷新,即使慢速刷新还是提示繁忙,等待10秒后,又正常显示了,说明对资源的熔断降级生效了。

3. Sentinel 控制台

3.1 本地控制台搭建

  1. 下载jar包;
  • 方式1:从 release 页面 下载最新版本的控制台 jar 包(sentinel-dashboard-1.8.2.jar);
  • 方式2:也可以从最新版本的源码自行构建 Sentinel 控制台;
  1. 启动jar包
java -Dserver.port=9000 -jar sentinel-dashboard-1.8.2.jar
  1. 访问Sentinel控制台

浏览器打开: http://localhost:9000/ 登陆账号密码默认均为sentinel;

3.2 客户端接入控制台

(参考官网,普通Springboot项目接入Sentinel控制台)
默认情况下Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。也可以配置
sentinel.eager=true ,取消Sentinel控制台懒加载。
打开浏览器即可展示Sentinel的管理控制台。

  1. 在客户端pom.xml引入 Transport 模块来与 Sentinel 控制台进行通信
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.2</version>
</dependency>
  1. 启动时加入 JVM 参数指定sentinel控制台的Ip和端口,并指定当前客户端的名称
-Dcsp.sentinel.dashboard.server=localhost:9000 -Dproject.name=sentinel-demo

完成以上步骤后即可在 Sentinel 控制台上看到对应的应用,机器列表页面可以看到对应的机器,如果看不到,就访问以下客户端,因为sentinel默认是懒加载;

  1. 将代码里的限流规则注释掉,在sentinel控制台添加限流规则
@RestController
public class TestContorl {

    @GetMapping("/hello")
    public String hello(){
        Entry entry = null;
        try { //限流入口
            entry = SphU.entry("Hello");
            return "Hello Sentinel!";  //这里就是被保护的资源
        }catch (BlockException ex){
            ex.printStackTrace();
            return "系统繁忙,稍后重试!";  //限流规则触发后的操作
        } finally {
            if (entry != null) {
                entry.exit();
            }

            ContextUtil.exit();
        }
    }

    // 定义限流规则
    // @PostConstruct 该注解的作用是在当前类的构造原函数执行之后执行的方法
    /*@PostConstruct
    public void initFlowRules(){
        //1. 创建存放限流规则的集合
        List<FlowRule> rules = new ArrayList<>();
        //2. 创建限流规则
        FlowRule rule1 = new FlowRule();
        // 定义资源
        rule1.setResource("Hello");
        // 定义限流规则类型
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置QPS的限流值
        rule1.setCount(2);

        //3. 将限流规则存放到集合中
        rules.add(rule1);
        //4. 加载限流规则
        FlowRuleManager.loadRules(rules);

    }*/
    
}

image
image

3.3 Sentinel 定义资源的方式

Sentinel 定义资源的方式有以下几种:

  • 抛出异常的方式
  • 返回布尔值方式
  • 异步调用支持
  • 注解方式
  • 主流框架的默认适配

3.3.1 抛出异常的方式

Sentinel中SphU包含了try-catch风格的API,用这种方式,当资源发生了限流之后会抛出BlockException异常。这个时候可以捕获异常,进行限流之后的逻辑处理,例如:
把需要控制流量的代码用 Sentinel API SphU.entry("HelloWorld") 和 entry.exit() 包围起来即可

try (Entry entry = SphU.entry("Hello")){ //限流入口,被保护的资源
        return "Hello Sentinel!";  //这里就是被保护的资源
    }catch (BlockException ex){
        ex.printStackTrace();
         return "系统繁忙,稍后重试!";  //限流规则触发后的操作
    } 

3.3.2 返回布尔值方式定义资源

Sentinel中SphO的API提供if-else风格的API,用这种方式,当资源发生了限流之后会返回false,这个时候可以根据返回值,进行限流之后的逻辑处理;

SphO.entry(xxx)需要与SphO.exit()成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException异常

定义一个测试的controller,然后在Sentinel控制添加对应资源的限流规则,查看限流时候生效;正常情况下,限流触发后会执行else里面的逻辑;

@RequestMapping("boolean-test")
    public String booleanTest(){
        if(SphO.entry("sentinel-boolean")){ //限流入口,被保护的资源名称
            try {
                // 被保护的资源...
                return "访问成功!";
            }finally {
                // SphO.entry(xxx)需要与SphO.exit()成对出现,否则会导致调用链记录异常,抛出ErrorEntryFreeException异常
                SphO.exit(); //限流出口
            }
        }else{
            // 限流规则被触发后的逻辑处理
            return "限流规则触发,访问失败!";
        }
    }

3.3.3 异步调用支持

Sentinel支持异步调用链路,在异步调用中,需要通过SphU.asyncEntry(XXX)定义资源,并需要在异步回调函数中调用exit方法;

  1. 在本地引用的引导类中添加注解@EnableAsync, 表示springboot项目开启异步调用支持;
@EnableAsync
@SpringBootApplication
public class SentinelDemoApplication {

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

}
  1. 创建SyncService编写异步调用方法
@Service
public class MyAsyncService {

    // @Async 注解表示该方法为异步调用方法
    @Async
    public void hello(){
        System.out.println("--->异步方法开始");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--->异步方法结束");
    }
}
  1. 在controller中调用异步方法,实现异步调用限流控制
    // Sentinel 对异步调用的支持
    @Autowired
    private MyAsyncService asyncService;
    @GetMapping("async")
    public void asyncTest(){
        // 1. 进行限流控制
        AsyncEntry asyncEntry = null;
        try {
            asyncEntry = SphU.asyncEntry("sentinel-async"); // 定义限流资源名称(限流入口)
            asyncService.hello(); // 异步方法调用
            System.out.println("----continue..."); // 异步方法调用后该语句继续执行
        } catch (BlockException e) {
            System.out.println("---> 系统忙,请稍后!");  // 被限流或降级触发后的逻辑处理
        }finally {
            if(asyncEntry != null){
                asyncEntry.exit();  // 限流出口
            }
        }

    }

3.3.4 注解方式定义资源

Sentinel支持通过注解 @SentinelResource 注解方式定义资源并配置 blockHandler 函数来进行限流之后的处理。
步骤:

  1. 引入相关依赖;
    因为Sentinel中使用AspectJ的扩展用于自定义资源、处理BlockException等,所以需要在项目中引入sentinel-annotation-aspectj依赖;
    <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-annotation-aspectj</artifactId>
            <version>1.8.2</version>
    </dependency>
  1. 创建AspectJ的配置类
@Configuration
public class SentinelAspectConfig {
    
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }
}
  1. 创建testController,进行测试验证;
   // Sentinel 注解方式定义资源
    @GetMapping("ann-test")
    @SentinelResource(value="sentinel-ann",blockHandler = "exceptionHandler")
    public String annationTest(){
        return "hello sentinel annotation";
    }

    // blockHandler函数
    public String exceptionHandler(BlockException ex){
        ex.printStackTrace();
        return "系统繁忙,请稍后";
    }

4. Sentinel高级

4.1 Sentinel 和 SpringCloud整合

SrpingCloudAlibaba 是阿里巴巴提供,致力于提供微服务开发的一站式解决方案。Spring Cloud Alibaba 默认为Sentinel 整合了Servlet、RestTemplate、FeignClient和Spring WebFlux。 Sentinel在Spring Cloud生态中,不仅不全了Hystrix在Servlet和RestTemplate这一块的空白,而且还兼容了Hystrix在FeignClent中限流降级的用法,并且支持运行时灵活配置和调整连休降级规则;

具体步骤

  1. 创建SpringBoot项目,在项目中引入spring-cloud-starter-alibaba-sentinel依赖
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  1. 创建Controller用来测试
@RestController
public class TestController {

    // Sentinel 注解方式定义资源
    @GetMapping("ann-tet")
    @SentinelResource(value="sentinel-ann",blockHandler = "exceptionHandler")
    public String annotionTest(){
        return "hello sentinel annotation";
    }

    // blockHandler函数
    public String exceptionHandler(BlockException ex){
        ex.printStackTrace();
        return "系统繁忙,请稍后";
    }

}
  1. application.properties配置文件中添加Sentinel控制台配置
# 应用名称
spring.application.name=springcloudsentinel-demo
# 应用服务 WEB 访问端口
server.port=8081
# 设置Sentinel控制台的主机地址和端口
spring.cloud.sentinel.transport.dashboard=localhost:9000

4.2 Sentinel对Fegin的支持

Sentinel适配了Feign组件。如果想要使用,除了引用spring-cloud-starter-alibaba-sentinel的依赖,还需要两个步骤:

  • 配置打开Sentinel对Feign的支持:feign.sentinel.enable=true
  • 加入spring-cloud-starter-openfeign依赖使Sentinel starter自动化配置类生效
  1. 引入Spring Cloud Alibaba Sentinel依赖

           <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
    
    
  2. 在application.properties配置文件中开启Sentinel对Feign的支持

    #设置Sentinel控制台的主机地址和端口
    spring.cloud.sentinel.transport.dashboard=localhost:9000
    #打开Sentinel对Feign的支持
    feign.sentinel.enabled=true
    
  3. 创建FallbackService,作为限流降级回调类,并在FeignAgent进行流控降级回调配置

    // 限流或降级的回调类
    @Component
    public class FallbackService implements FeignAgent {
        //限流和降级的处理
        @Override
        public String hello() {
            return "系统繁忙,请稍候";
        }
    }
    
    

定义feign客户端接口

// feign 客户端
@FeignClient(value = "sentinel-feign-provider", fallback = FallbackService.class)
public interface FeignAgent {

    @GetMapping("/api/v1/hello")
    String hello();
}

服务消费者的测试controller

@RestController
public class TestController{
	@Autowired
	private FeignAgent feignAgent;
	
	@GetMapping("/hello")
	public String hello(){
		return feignAgent.hello();
	}
}
  1. 设置限流规则测试

    Sentinel与Feign整合时,流控规则的编写形式为:http请求方式:协议://服务名/请求路径和参数(请求路径和参数为@FeignClient中的请求路径,也就是本服务调用下游服务的URL)

    例如:GET:http://sentinel-feign-provider/api/v1/hello

    如果快速刷新http://localhost:8090/api/v1/consumer/hello,会出现系统繁忙,请稍候

  2. 请求地址中包含参数的资源名配置

    如果是多个@RequestParam,资源名不需要带上@RequestParam, 如果请求路径中包含@PathVariable,案例如下:

    sentinel控制台资源名定义为:GET:http://sentinel-feign-provider/api/v1/hello/{hello}

    @FeignClient(value = "sentinel-feign-provider", fallback = FallbackService.class)
    public interface FeignAgent {
    
        @GetMapping("/api/v1/hello/{hello}")
        String hello(@PathVariable(value = "hello") String hello);
    }
    

4.3 Sentinel 对 Spring Cloud Gateway 的支持

Sentinel整合Spring Cloud gateway

  1. 在gateway的pom.xml中引入依赖;

           <!-- Spring Cloud Alibaba Sentinel 依赖 -->
    		<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
                <version>2.2.3.RELEASE</version>
            </dependency>
           <!-- Sentinel支持Spring Cloud Gateway 的依赖 -->
    		<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
                <version>2.2.3.RELEASE</version>
            </dependency>
    
  2. 创建GatewayConfiguration配置类,配置流控降级回调操作;

    @Component
    public class GatewayConfiguration {
         @PostConstruct
        public void doInit(){
             //设置限流或降级的回调函数
             GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
                 @Override
                 public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, java.lang.Throwable throwable) {
                    return ServerResponse.status(200).syncBody("系统繁忙请稍后");
                 }
             });
         }
    }
    
    
  3. application.yaml中配置sentinel控制台访问地址;

    spring:
      cloud:
        sentinel:
          transport:
            port: 8718
            dashboard: 127.0.0.1:8080
    
  4. 运行测试;

sentinel在适配spring cloud gateway时提供了两种配置规则:

  • route维度:即在spring配置文件配置的路由条数,资源名为对应的routeId;
  • 自定义API维度:用户可以利用Sentinel提供的API来自定义一些自定义分组;

在sentinel控制台中,添加网关限流规则的界面跟普通限流规则的界面不太相同,如下图:

API类型选择Route ID , 就是输入gateway中路径的routeid; 如果选择的是API分组,就需要先在Sentinel控制台网关目录下的菜单“API管理” 里定义API分组,然后在添加留空规则的这个界面上选择API分组;

image

4.4 系统自适应保护

Sentinel系统自适应限流是从应用的整体维度进行入口流量控制,结合应用的Load,CPU使用率,总体平均RT,入口QPS和并发线程数等几个维度的监控指标,通过自适应的流控策略,来让系统入口流量和系统的负载达到一个平衡,让系统尽可能保持最大吞吐量的同时保证系统整体的稳定性;

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

同样,系统自适应保护规则设置也有两种方式:

  • 本地代码方式;
  • Sentinel控制台动态配置;
@RestController
public class SysController {

    // 这里定义的资源就没有定义资源的名称和处理函数了,因为系统自适应的维度是整个应用,sentinel也会有默认的限流和降级的处理函数;
    // EntryType.IN 表示这是一个入口资源,自适应保护也只对这样的入口资源生效;
    @SentinelResource(entryType = EntryType.IN)
    @RequestMapping("/sys")
    public String sysHello(){
        return "hello sentinel!";
    }

    // 代码方式定义规则
    @PostConstruct
    private void initSystemRule(){
        //1. 创建存放限流规则的集合
        List<SystemRule> rules = new ArrayList<>();
        //2. 创建自适应规则
        SystemRule rule = new SystemRule();
        // 设置入口QPS
        rule.setQps(2);
        //3. 将限流规则存放到集合中
        rules.add(rule);
        //4. 加载限流规则
        SystemRuleManager.loadRules(rules);
    }

}

上面是通过本地代码的方式来定义了限流规则,在Sentinel控制台中添加系统自适应的限流规则的菜单路径是[应用名]-系统规则-新增系统规则


(以下内容没看太明白--!)

4.5 Sentinel授权控制

如果需要根据调用来源来判断该次请求是否运行放行,这个时候可以使用Sentinel的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(Origin)判断资源访问时候通过。

若配置白名单,则只有来源于白名单的请求才可通行;如果配置的是黑名单,则黑名单内的请求来源将被拒绝,其他请求放行;

重要属性

来源访问规则(AuthorintyRule),主要有以下配置项:

  • resource: 资源名,即限流规则的作用对象。
  • limitApp: 请求来源,对应的黑白名单,多个用“,”分隔,如:appA,appB 。
  • strategy: 限制模式,AUTHORITY_WHITE 为白名单模式; AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。

实现方式

  • 本地代码方式;
  • Sentinel控制台动态配置方式;

4.5.1 本地代码方式

添加测试controller,并在代码中定义白名单规则

@RestController
public class AuthorintyTestControl {

    // 定义资源名以及限流回调方法
    @SentinelResource(value = "white_rule",blockHandler = "exceptionHandler")
    @GetMapping("/white-test")
    public String whiteListTest(){
        return "AuthorintyTestControl";
    }

    // 资源被限流/降级时调用
    public String exceptionHandler(BlockException ex){
            return "系统繁忙,请稍后。";
    }


    // 代码方式定义白名单规则
    @PostConstruct
    private static void initWhiteRules(){
        //1. 创建存放限流规则的集合
        List<AuthorityRule> rules = new ArrayList<>();
        //2. 创建自适应规则
        AuthorityRule rule = new AuthorityRule();
        // 设置授权模式为 白名单模式
        rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
        // 设置白名单
        rule.setLimitApp("192.168.0.104");
        //3. 将限流规则存放到集合中
        rules.add(rule);
        //4. 加载限流规则
        AuthorityRuleManager.loadRules(rules);
    }
}

添加配置类,设置请求来源解析

import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

/**
 * @author: linwei
 * @date: 2021/9/2 22:29
 * @Description:  创建配置类,设置请求来源解析
 */

@Component
public class SentinelConfig {

    @PostConstruct
    public void init(){
        // 获取请求来源的ip地址
        WebCallbackManager.setRequestOriginParser(new RequestOriginParser() {
            @Override
            public String parseOrigin(HttpServletRequest httpServletRequest) {
                return httpServletRequest.getRemoteAddr();
            }
        });
    }
}

4.5.2 Sentinel控制台配置方式

使用控制台配置时,把上面controller中代码里定义的规则注释掉,避免引起混乱,然后在sentinel控制台菜单“授权规则”中添加新的授权规则;

然后在浏览器进行测试即可;

4.6 Sentine动态规则

前面不管是通过Java代码还是通过Sentinel控制台去设置限流规则,都属于手动方式,不够灵活。这种方式一般用于测试和演示,生产环境上一般通过动态设置规则的方式来管理限流规则。也就是说,很多时候限流规则会被存储在文件、数据库或配置中心。Sentinel的DataSource接口给我们提供了对接任意配置源的能力。

(课程中使用的是Zookeeper作为配置中心,不过现在可能最多的是使用Nacos做为配置中心。之所以使用配置中心,也是为了应用重启后,规则丢失的问题。)

posted @ 2021-08-31 22:32  穷苦书生  阅读(279)  评论(0编辑  收藏  举报