阅读本文大概需要20分钟,但是还是要动手实验的哈,实践是检验真理的唯一标准。感觉博主整理的不错的可以给个关注,本号后续陆续推出干货

流量控制&熔断降级产品对比



Sentinel

Hystrix

Resilience4j

隔离策略

信号量隔离(并发线程数隔离)

线程池隔离/信号量隔离

信号量隔离

熔断降级策略

基于响应时间、异常比率、异常数

基于异常比率

基于异常比率、响应时间

实时统计实现

滑动窗口

滑动窗口

Ring Bit Bufffer

动态规则配置

支持多种数据源

支持多种数据源

有限支持

扩展性

多个扩展点

插件的形式

接口的形式

基于注解的支持

支持

支持

支持

限流

基于QPS,支持基于调用关系的限流

有限的支持

Rate Limiter

流量整形

支持预热模式、匀速器模式、预热派对模式

不支持

简单的Rate Limiter

系统自适应保护

支持

不支持

不支持

控制台

提供开箱即用的控制台、可配置规则、查看秒级监控、机器发现

简单的监控查看

Sentinel 介绍

Sentinel 概述

Sentinel是阿里巴巴出品的面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护等多个维度来保障微服务的稳定性

Sentinel 组成

  • 核心库:主要是指Java客户端,不依赖任何框架、库,能够运行与java7及以上的版本运行时环境,同时对Dubbo、Spring Cloud等框架也有较好的支持
  • 控制台:控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等

Sentinel 特性



限流框架 java java 限流组件_spring

Sentinel 相关概念

资源

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

规则

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

Sentinel 优势

  • 友好的控制面板
  • 支持实时监控
  • 支持多种限流、支持QPS限流,线程数限流以及多种限流策略
  • 支持多种降级模式、支持按平均返回时间降级,按多种异常数降级、按异常比率降级等
  • 方便扩展开发,支持SPI模式对chain进行扩展
  • 支持链路的关联、可以实现按照链路统计限流,系统保护,热门资源保护等

SpringBoot+Sentinel

SpringBoot 环境信息

  • SpringBoot 2.1.4.RELEASE
  • JDK8
  • Sentinel 1.7.2

内置加载限流规则

  • pom加入sentinel依赖
<dependency>
			<groupId>com.alibaba.csp</groupId>
			<artifactId>sentinel-core</artifactId>
			<version>1.7.2</version>
		</dependency>
  • 创建TestController
@RestController
public class TestController {
    @GetMapping("/hello")
    public String hello(){
    // 限流的资源名称
        try (Entry entry = SphU.entry("hello")){
            return "hello sentinel";
        }catch (BlockException e){
            return "系统繁忙,请稍后";
        }
    }
    @PostConstruct
    public void initFlowRules(){
        List<FlowRule> list = new LinkedList<>();
        FlowRule rule = new FlowRule();
        // 限流资源名称
        rule.setResource("hello");
        // 限流策略
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 限流数量定义QPS每秒能通过的请求个数
        rule.setCount(2);
        list.add(rule);
        // 加载限流规则
        FlowRuleManager.loadRules(list);
    }
}
  • 此时启动应用,访问资源hello,每秒慢速点击访问可以正常访问,如果快速点击出现系统繁忙,请稍后

限流框架 java java 限流组件_spring_02

通过上面我们也能看到限流规则是在代码中写好的, 如果后续要修改的话,需要重新编译非常的麻烦,现在Sentinel提供了一个控制台,通过控制台我们就能动态的修改限流规则,现在我们看下怎么使用Sentinel控制台来实现限流策略

Sentinel 控制台启动

  • 下载地址:https://github.com/alibaba/Sentinel/releases
  • 启动
java -Dserver.port=8850 -jar sentinel-dashboard-1.8.4.jar
  • 浏览器访问 localhost:8050 账号密码默认sentinel sentinel

SpringBoot应用与Sentinel控制台绑定

  • pom加入依赖
<dependency>
			<groupId>com.alibaba.csp</groupId>
			<artifactId>sentinel-transport-simple-http</artifactId>
			<version>1.7.2</version>
		</dependency>
  • JVM启动时添加参数
-Dcsp.sentinel.dashboard.server=localhost:8850
-Dproject.name=SentinelQuickStartDemo
  • 重启应用并通过浏览器访问 /hello接口几次,查看控制台中实时监控效果
  • 动态设置限流规则
  • 首先取消代码中的规则设置,注释掉规则代码

限流框架 java java 限流组件_spring_03

  • 打开控制台设置限流规则

限流框架 java java 限流组件_限流框架 java_04

限流框架 java java 限流组件_限流_05

限流框架 java java 限流组件_Cloud_06

  • 访问应用接口,查看限流规则是否生效

限流框架 java java 限流组件_Cloud_07

Sentinel 定义资源的方式

Sentinel除了基本的定义资源的方式外,还有其它的定义资源的方式,具体如下:

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

抛出异常的方式定义资源

Sentinel中的SphU包含try-catch风格的api。用这种方式,当资源发生限流之后会抛出BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理,而我们在上面就使用了这种方式进行定义资源,关键代码如下:

// 使用限流规则监控保护资源
try (Entry entry = SphU.entry("hello")){
// 被保护的资源
            return "hello sentinel";
        }catch (BlockException e){
        // 被限流或者降级的处理
            return "系统繁忙,请稍后";
        }

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

  • 定义资源保护访问
@RestController
public class TestBooleanController {
    @GetMapping("/boolean")
    public boolean hello(){
        if (SphO.entry("Sentinel_Boolean")){
            try {
                System.out.println("Hello Sentinel");
                return true;
            }finally {
                SphO.exit();
            }
        }else{
            // 限流降级的处理
            System.out.println("系统繁忙,请稍后");
            return false;
        }
    }

}
  • 新增限流规则

限流框架 java java 限流组件_限流_08

  • 查看访问结果

限流框架 java java 限流组件_Cloud_09

异步调用支持方式

  • 开启异步支持
// @EnableAsync 开启异步支持
@EnableAsync
@SpringBootApplication
public class SentinelApplication {

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

}
  • 添加异步访问方法
    新建AcyncService方法
@Service
public class AsyncService {
    @Async
    public void hello(){
        System.out.println("异步开始======");
        try {
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("异步结束======");
    }
}
  • 添加异步访问资源
@RestController
public class TestAsyncController {
    @Autowired
    AsyncService asyncService;
    @GetMapping("/async")
    public void hello(){
        AsyncEntry asyncEntry = null;
        try {
            asyncEntry = SphU.asyncEntry("Sentinel_Async");
            asyncService.hello();
        }catch (BlockException e){
            System.out.println("系统繁忙,请稍后");
        }finally {
            if (asyncEntry != null ){
                asyncEntry.exit();
            }
        }

    }

}
  • 添加限流规则
  • 查看访问效果

限流框架 java java 限流组件_限流框架 java_10

注解方式调用支持

  • 添加注解支持的依赖
<dependency>
			<groupId>com.alibaba.csp</groupId>
			<artifactId>sentinel-annotation-aspectj</artifactId>
			<version>1.7.2</version>
		</dependency>
  • 创建Aspect配置类
@Configuration
public class AspectConfig {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
        return new SentinelResourceAspect();
    }
}
  • 创建限流访问资源代码
@RestController
public class TestAnnController {
    @Autowired
    AsyncService asyncService;
    @SentinelResource(value = "Sentinel_Ann",blockHandler = "exceptionHandler")
    @GetMapping("/ann")
    public String hello(){

        return "Hello Sentinel";
    }
    public void exceptionHandler(BlockException e){
        e.printStackTrace();
        System.out.println("系统繁忙,请稍后");
    }

}

主流框架的默认适配

为了减少开发的复杂程度,对大部分的主流框架,例如Web Servlet,Dubbo、Spring Cloud、gRPC、Spring WebFlx、Reactor等都做了适配,只需要引入对应的依赖就可以方便的整合Sentinel

SpringCloud+Sentinel

下面是整理本文时阅读的一些资料汇总,有兴趣的可以去看看



限流框架 java java 限流组件_spring_11

版本参考地址

SpringCloud

SpringCloud Alibaba

SpringCloud Alibaba 版本对应关系

SpringCloud版本详细对应关系

Nacos-SpringCloud版本

步骤

  • springcloud 版本
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • pom 加入sentinel依赖
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  • 创建限流资源代码
@RestController
public class TestController {
    @SentinelResource(value = "Sentinel_SpringCloud",blockHandler = "exceptionHandler")
    @GetMapping("/ann")
    public String hello(){
        return "hello sentinel";
    }
    public String exceptionHandler(BlockException e){
        e.printStackTrace();
        return "系统繁忙,请稍后";
    }
}
  • 配置项目链接控制台
spring.application.name=SpringCloudSentinel
spring.cloud.sentinel.transport.dashboard=localhost:8850
  • 创建限流规则

Sentinel+Feign

  • 引入feign+sentinel的依赖
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.0.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>io.github.openfeign</groupId>
                    <artifactId>feign-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>10.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 定义服务提供类,ServiceProvider 中修改
@EnableDiscoveryClient
@SpringBootApplication
public class ServerProviderApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServerProviderApplication.class, args);
	}
	@Slf4j
	@RestController
	static class TestController {
		@GetMapping("/hello/{str}")
		public String hello(@PathVariable String str) {
			log.info("invoked name = " + str);
			return "hello " + str;
		}
		@GetMapping("/test")
		public String test() {
			return "hello sentinel";
		}
	}

}
  • 增加feign客户端的支持
@SpringBootApplication
// 开启feign-client
@EnableFeignClients
public class SentinelApplication {

    public static void main(String[] args) {

        SpringApplication.run(SentinelApplication.class, args);
    }

}
  • 定义远程调用接口
@FeignClient(value = "alibaba-nacos-discovery-server",fallback = FallBackService.class)
public interface FeignAgent {
    @GetMapping("/test")
    String hello();
}
  • 定义回调降级类
@Component
public class FallBackService implements FeignAgent {
    @Override
    public String hello() {
        return "系统繁忙,请稍后";
    }
}
  • 配置项目链接sentinel控制台,开始sentinel对feign的支持
spring.application.name=SpringCloudSentinel
spring.cloud.sentinel.transport.dashboard=localhost:8850
# feign-sentinel 支持
feign.sentinel.enabled=true
  • 启动注册中心nacos,服务提供者serviceProvider和sentinel客户端
  • 定义限流规则,Sentinel和Feign整合时,限流规则的编写形式为:
http请求方式:协议://服务名/请求路径跟参数
例:GET:http://alibaba-nacos-discovery-server/test

限流框架 java java 限流组件_限流框架 java_12

Sentinel+SpringCloud Gateway

  • 引入依赖
<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-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  • 配置gateway信息,链接Sentinel控制台
spring:
  application:
    name: SpringCloudGateWay
  cloud:
    gateway:
      routes:
      # id: sentinel-feign-gateway 限流时route id使用这个
        - id: sentinel-feign-gateway
          uri: lb://SpringCloudSentinel:8002
          predicates:
          # Path=/feign/** 自定义API维度限流使用
            - Path=/feign/**
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: 127.0.0.1:8850

server:
  port: 8003
  • 配置限流时返回内容
@Component
public class GatewayConfiguration {
    @PostConstruct
    public void doInit(){
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                return ServerResponse.status(200).syncBody("系统繁忙,请稍后");
            }
        });
    }
}
  • 启用服务发现
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {

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

}

限流规则配置

  • route id

限流框架 java java 限流组件_限流框架 java_13

  • 自定义API维度

限流框架 java java 限流组件_限流框架 java_14

流量控制实现

Sentinel的所有规则都可以在内存态中动态的查询及修改,修改之后立即生效。同时Sentinel也提供API,选择定制自己的规则策略

Sentinel主要支持以下几种规则

  • 流量控制规则
  • 熔断降级规则
  • 系统保护规则
  • 来源访问控制规则
  • 动态规则扩展

流量控制规则实现

流量控制(flow control),其原理是监控应用流量的QPS或并发线程数等指标,当达到制定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性

流量控制主要有两种方式

  • 并发线程数:并发线程数限流用于保护业务线程数不被耗尽
  • QPS:当QPS超过某个阈值的时候,则采取措施进行流量控制

一条限流规则主要由下面几个元素组成,我们可以组成这些元素来实现不同的限流效果:

  • resource:资源名,即限流的对象
  • count:限流阈值
  • grade:限流阈值类型(QPS或并发线程数)
  • limitApp:流控针对的调用来源,若为default则不区分调用来源
  • strategy:调用关系限流策略
  • controBehavior:流量控制效果(直接拒绝,Warm Up,匀速排队)

FlowException

  • .这种方式适用与对系统处理能力确切已知的请求下,比如通过压测确定了系统的准确水位时
  • Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热,冷启动方式,当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过“冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间。避免冷系统被压垮
  • 排队等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法

同一个资源可以同时由多个限流规则,检查规则时会依次检查

熔断降级

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



Field

说明

默认值

resource

资源名,即限流规则的对象

count

阈值

grade

熔断策略,支持秒级RT/秒级异常比例/分钟级异常数

秒级平均RT

timeWindow

降级的时间,单位为s

reSlowRequestAmount

RT模式下1秒内连续多少个请求的平均RT超出阈值方可触发熔断(1.7.0引入)

5

minRequestAmount

异常熔断的触发最小请求数,请求数小于该值时及时异常比率超出阈值也不会熔断(1.7.0引入)

5

同一个资源可以有多个降级规则

熔断策略详解

  • 平均响应时间(DEGRADE_GRADE_RT):当1s内连续进入N个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以ms为单位),那么接下来的时间(DegradeRule 中的timeWindow,以s为单位)之内,对这个方法的调用都会自动熔断
  • 异常比例(DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量>=N(可配置),并且每秒异常总数占通过量的比值超过阈值(DegradeRule中的count)之后,资源进入降级状态,即在接下的时间(DegradeRule 中的timeWindow,以s为单位)之内,对这个方法调用都会自动的返回。异常比率的阈值范围时[0.0,1.0],代表0%-100%
  • 异常数(DEGRADE_GRADE_EXCEPTION_COUNT):当资源近一分钟的异常数目超过阈值之后就会进行熔断。注意由于统计时间时分钟级别的,若timeWindow小于60s,则结束熔断状态后仍可能再进入熔断状态

熔断降级设计理念

在限制的手段上,Sentinel和Hystrix采取完全不一样的方法

Hystrix通过线程池隔离的方式,来对依赖(在Sentinel的概念中对应资源)进行了隔离,这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本(过多的线程池导致线程数目过多)还需要预先给各个资源做线程池大小的分配

Sentinel对这个问题采取了两种手段

  • 通过并发线程数进行限制
    和资源池隔离的方法不同,Sentinel通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会导致线程数的逐步累积,当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝,堆积的线程完成任务后才开始继续接收请求
  • 通过响应时间对资源进行降级
    除了对并发线程数进行控制以外,Sentinel还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复

系统自适应保护实现

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

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

系统规则支持一下的模式

maxQps*minRt

  • 估算得出,设定参考值一般是

CPU cores * 2.5

  • CPU usage (1.5.0版本):当系统CPU使用率超过阈值即出发系统保护(取值范围0.0-1.0)比较灵敏
  • 平均RT:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护
  • 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护

重要的属性



Field

说明

默认值

highestSystemLoad

load1触发值,用于触发自适应控制阶段

-1(不生效)

avgRt

所有入口流量的平均响应时间

-1(不生效)

maxThread

入口l巨量的最大并发数

-1(不生效)

qps

所有入口资源的QPS

-1(不生效)

highestCpuUsage

当前系统的CPU使用率(0.0-1.0)

-1(不生效)

代码控制

@RestController
public class TestLoadController {

    @SentinelResource(entryType = EntryType.IN)
    @GetMapping("/rule")
    public String hello(){
        return "hello sentinel rule";
    }


//    @PostConstruct
//    public void initDegradeRule(){
//        List<SystemRule> rules = new LinkedList<>();
//       SystemRule rule = new SystemRule();
//       rule.setQps(2);
//       rules.add(rule);
//        SystemRuleManager.loadRules(rules);
//    }


}

控制台配置

系统设置

授权控制

很多时候,我们需要根据调用来源来判断请求是否允许放行,这时候可以使用Sentinel的来源访问控制(黑白名单控制)的功能,来源访问控制根据资源的请求来源(origin)判断资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过

重要属性

  • resource: 资源名,即限流规则的对象
  • limitApp: 请求来源,对应的黑名单/白名单,多个用“,"分割
  • strategy:限制模式,AUTHORITY_WHITE为白名单模式,AYTHORITY_BLACK为黑名单模式,默认为白名单模式

代码配置

  • 黑白名单配置
@RestController
public class WhiteBlackController {

    @SentinelResource(value = "Sentinel_Rule",blockHandler = "exceptionHandler")
    @GetMapping("/rule")
    public String hello(){
        return "hello sentinel rule";
    }
    public String exceptionHandler(BlockException e){
        e.printStackTrace();
        return "系统繁忙,请稍后";
    }

    @PostConstruct
    public void initWhiteRules(){
       List<AuthorityRule> rules = new LinkedList<>();
       AuthorityRule rule = new AuthorityRule();
       rule.setResource("Sentinel_Rule");
       rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
       rule.setLimitApp("192.168.168.168");
       rules.add(rule);
        AuthorityRuleManager.loadRules(rules);
    }

    @PostConstruct
    public void initBlackRules(){
        List<AuthorityRule> rules = new LinkedList<>();
        AuthorityRule rule = new AuthorityRule();
        rule.setResource("Sentinel_Rule");
        rule.setStrategy(RuleConstant.AUTHORITY_BLACK);
        rule.setLimitApp("127.0.0.1");
        rules.add(rule);
        AuthorityRuleManager.loadRules(rules);
    }

}
  • 获取IP配置
@Component
public class SentinelConfig {
    @PostConstruct
    public void init(){
        WebCallbackManager.setRequestOriginParser(new RequestOriginParser() {
            @Override
            public String parseOrigin(HttpServletRequest httpServletRequest) {
                return httpServletRequest.getRemoteAddr();
            }
        });
    }
}

动态规则设置

拉模式拓展

实现拉模式的数据源最简单的方式是继承AutoRefreshDataSource抽象类,然后实现readSource()方法,在该方法里从指定数据源读取字符串格式的配置数据。

推模式拓展

实现推模式的数据源最简单的方式是继承 AbstractDataSource 抽象类,在其构造方法中添加监听器,并实现 readSource() 从指定数据源读取字符串格式的配置数据。比如 基于 Nacos 的数据源

推模式:使用Nacos配置规则

  • pom加入依赖
<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.7.1</version>
        </dependency>
  • 动态配置规则
@Component
public class SentinelDataSourceConfig {
    private static final String KEY = "TestResource";
    // nacos server ip
    private static final String remoteAddress = "localhost:8848";
    // nacos group
    private static final String groupId = "Sentinel_Demo";
    // nacos dataId
    private static final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule";
    // if change to true, should be config NACOS_NAMESPACE_ID
    private static boolean isDemoNamespace = false;
    // fill your namespace id,if you want to use namespace. for example: 0f5c7314-4983-4022-ad5a-347de1d1057d,you can get it on nacos's console
    private static final String NACOS_NAMESPACE_ID = "${namespace}";

    @PostConstruct
    private static void loadRules() {
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

    private static void loadMyNamespaceRules() {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, remoteAddress);
        properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE_ID);

        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, dataId,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }
}
  • 发送nacos配置,或者手动创建
public static void main(String[] args) throws Exception {
        final String remoteAddress = "localhost:8848";
        final String groupId = "Sentinel_Demo";
        final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule";
        final String rule = "[\n"
                + "  {\n"
                + "    \"resource\": \"Sentinel_SpringCloud\",\n"
                + "    \"controlBehavior\": 0,\n"
                + "    \"count\": 5.0,\n"
                + "    \"grade\": 1,\n"
                + "    \"limitApp\": \"default\",\n"
                + "    \"strategy\": 0\n"
                + "  }\n"
                + "]";
        ConfigService configService = NacosFactory.createConfigService(remoteAddress);
        System.out.println(configService.publishConfig(dataId, groupId, rule));
    }

行了,到这就结束了,本来打算简单整理一下,但是发现越整理越多,而且真的是没有试验一切都是刷流氓,快去写个demo体验下Sentinel的丝滑吧