【深入理解SpringCloud微服务】Sentinel功能详解

Sentinel功能详解

上一篇文章《Sentinel实战与原理剖析》我们没有对Sentinel的功能进行讲解,本篇文件将对它们进行详细的解析。

Sentinel控制台

首先要下载Sentinel控制台的jar包,或者下载sentinel-dashboard的源码自行编译也可以。

然后启动控制台:

引入maven依赖:

xml 复制代码
	<dependencies>
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
			<version>2.2.9.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>2.3.12.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
			<version>2.3.12.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-bootstrap</artifactId>
			<version>3.0.2</version>
		</dependency>
	</dependencies>
  • spring-cloud-starter-alibaba-sentinel:Sentinel的starter,里面包含了sentinel-transport-simple-http、sentinel-annotation-aspectj、sentinel-spring-webmvc-adapter等依赖,并且自带自动配置,比起单独引入sentinel-core、sentinel-transport-simple-http等方便许多
  • spring-boot-starter-actuator:Sentinel控制台依赖需要通过actuator暴露的端点收集服务监控信息,以在"实时监控"中进行展示。
  • spring-cloud-starter-bootstrap:启动时加载bootstrap配置文件。

bootstrap.yml文件:

yml 复制代码
server:
  port: 8888

spring:
  application:
    name: demo
  cloud:
    sentinel:
      transport:
      	# sentinel控制台的地址
        dashboard: 127.0.0.1:8080
        # 本服务以sentinel控制台交互的端口
        port: 8719

# 暴露actuator的/actuator/sentinel端点        
management:
  endpoints:
    web:
      exposure:
        include: '*'   

编写一个简单的Controller:

java 复制代码
/** 
 * @author huangjunyi 
 * @date 2024年4月13日 上午8:19:32
 * @desc 
 */
@RestController
public class HelloController {
	
	@GetMapping("/hello")
	public String hello() {
		return "hello world";
	}

}

启动服务,测试/actuator/sentinel端点是否正常暴露:

调一遍/hello接口,这样Sentinel才会有信息。

进入控制台查看,默认账号密码是sentinel/sentinel。

在【簇点链路】可以查看接口信息:

配置流控规则:

调用/hello接口测试流控规则:

【实时监控】可以查看不同时间点的通过QPS、拒绝QPS、响应时间(ms):

流控规则

流控规则可以设置【阈值类型】、【流控模式】、【流控效果】,其中【流控效果】只有当【阈值类型】是QPS是,才能设置。

阈值类型

【阈值类型】可以设置QPS或并发线程数,QPS是每秒请求数,如果设置为QPS的话,那么当接口的每秒请求数达到指定阈值时,则触发限流,设置为并发线程数时也是类似的规则。

流控模式

【流控模式】有"直接"、"关联"、"链路"三种。

直接

以【阈值类型】为QPS为例:"直接"就是当QPS指定资源名对应的接口QPS达到单机阈值设置的值时,该接口后续的请求将被限流。比如以下例子,当/hello接口的QPS达到2时,则后续的请求将会被限流。

关联

"关联"是指关联资源达到阈值后,当前资源则被限流。

我们改造一下接口:

java 复制代码
/** 
 * @author huangjunyi 
 * @date 2024年4月13日 上午8:19:32
 * @desc 
 */
@RestController
public class HelloController {
	
	@Autowired
	private RestTemplate restTemplate;
	
	@GetMapping("/hello")
	public String hello() {
		return "hello " + restTemplate.getForObject("http://localhost:8888/world", String.class);
	}
	
	@GetMapping("/world")
	public String world() {
		return "world";
	}
	
	@GetMapping("/my")
	public String my() {
		return "my " + restTemplate.getForObject("http://localhost:8888/world", String.class);
	}

}

现在/hello接口和/my接口,都会调用到/world接口。

控制台配置:

那么此时关联资源(/world接口)的QPS达到2时,后续对当前资源(/hello接口)的请求都会被限流。

链路

"链路"是指当前资源的QPS达到阈值时,入口资源会被限流。

由于"链路"模式的当前资源必须是被@SentinelResource注解修饰的,并且入口资源只能通过方法调用的方式调用当前资源,不能通过http请求的方式进行调用,否则会不生效。因此改造一下工程:

把/world接口抽成Service接口,/hello和/my两个接口调用world():

java 复制代码
/** 
 * @author huangjunyi 
 * @date 2024年4月13日 上午8:19:32
 * @desc 
 */
@RestController
public class HelloController {
	
	@Autowired
	private HelloService helloService;
	
	@GetMapping("/hello")
	public String hello() {
		return "hello " + helloService.world();
	}
	
	@GetMapping("/my")
	public String my() {
		return "my " + helloService.world();
	}

}

Service添加@SentinelResource注解:

java 复制代码
/** 
 * @author huangjunyi 
 * @date 2024年4月13日 下午2:24:56
 * @desc 
 */
@Service
public class HelloService {
	
	@SentinelResource("world")
	public String world() {
		return "world";
	}

}

此时接口调用情况变成如下这样:

然后进行规则配置:/hello接口和/my接口都调用了wolrd接口,那么像下面这样配置之后,当world接口的QPS达到限流阈值时,入口资源对应的/hello接口就会被限流。

注意,为了要让链路模式流控规则生效,还要配置入口资源关闭聚合。

可以添加配置spring.cloud.sentinel.web‐context‐unify: false。

yaml 复制代码
server:
  port: 8888

spring:
  application:
    name: demo
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
        port: 8719
      # 入口资源关闭聚合
      web-context-unify: false
        
management:
  endpoints:
    web:
      exposure:
        include: '*'   

或者引入sentinel-web-servlet依赖,并添加一个CommonFilter过滤器,给CommonFilter添加初始化属性CommonFilter.WEB_CONTEXT_UNIFY为false。

xml 复制代码
		<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
            <version>1.8.5</version>
        </dependency>
java 复制代码
    @Bean
    public FilterRegistrationBean<CommonFilter> sentinelFilterRegistration() {
        FilterRegistrationBean<CommonFilter> registration = new FilterRegistrationBean();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        // 入口资源关闭聚合
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelFilter");
        registration.setOrder(1);
        return registration;
    }

流控效果

【流控效果】指的是底层的限流算法,配置不同的流控效果,那么Sentinel底层使用的限流算法就不一样,自然就有不同的流控效果。

快速失败

使用的是滑动时间窗算法,统计每秒的QPS数,达到阈值则限流。

比如下面配置的单机阈值为2,流控效果为快速失败,那么Sentinel底层使用滑动时间窗算法统计每秒的QPS,当前资源的QPS达到2时,后续对当前资源的请求都会被限流。

Warm Up

使用的是令牌桶算法,需要配置【预热时长】,在【预热时长】内限流阈值会均衡增长,直到达到了【预热时长】后,限流阈值增加到【单机阈值】指定的值。

比如下面配置【流控效果】为"Warm Up",指定【预热时长】为5,【单机阈值】为10。那么服务起订之后,当前资源("/hello"接口)的限流阈值将会在5秒内匀速增长达到10。

排队等待

当配置的【流控效果】为"排队等待"时,【单机阈值】指的是每秒匀速处理的请求个数,然后还有配置【超时时间】表示当请求被限流时,等待的超时时长。

比如下面配置【流控效果】为"排队等待",【单机阈值】为10,【超时时间】为200,那么表示当前资源("/hello"接口)每秒处理10个请求,当请求被限流时,等待200毫秒。

熔断降级规则

熔断规则里面需要配置【熔断策略】,包含熔断策略:"慢调用比例"、"异常比例"、"异常数"。

然后最下面三个配置项是固定配置项。

  • 熔断时长:当触发熔断时,断路器打开的时长。
  • 最小请求数:当指定【统计时长】内请求数达到最小请求数时,熔断规则才生效。
  • 统计时长:熔断规则的统计时长。

慢调用比例

当【熔断策略】配置为"慢调用比例时",需要设置【最大 RT】和【比例阈值】两个配置项。【最大 RT】是指最大响应时间,当一次请求的响应时长超过了这个时间限制时,就会被记为一次慢调用;【比例阈值】是指触发熔断的慢调用比例,当【统计时长】内的慢调用比例阈值达到了【比例阈值】指定的比例值时,触发熔断。

异常比例

当【熔断策略】配置为"异常比例"时,需要配置【比例阈值】配置项,该配置项指的是当前资源在【统计时长】指定的时长内异常比例达到了【比例阈值】指定的比例值时,触发熔断。

异常数

当【熔断策略】配置为"异常数"时,需要配置【异常数】配置项,当前资源在【统计时长】的时长内异常数达到【异常数】指定的数值时,触发熔断。

热点参数规则

热点参数限流需要指定参数,因此我们改造一下/hello接口,添加一个接口参数。

java 复制代码
	@GetMapping("/hello")
	public String hello(@RequestParam int num) {
		return "hello " + helloService.world();
	}

【热点规则】中的配置项包含:参数索引、统计窗口时长、单机阈值、参数类型、参数值、限流阈值。

比如像下面这样配置后,当我们请求/hello?num=1在5秒内超过2次是则被限流,而num参数是其他值时则在5秒内超过3次时被限流。

系统自适应保护

【系统保护规则】是用于保护整个服务的,而不是针对一个服务中的某个资源进行保护。

【系统保护规则】需要配置"阈值类型"以及与之对应的阈值,当系统的对应指标达到了阈值时,后续对该系统的所有请求都将被限流。

阈值类型包括:

  • LOAD:系统负载,就是Linux的top命令里load average的第一个值
  • RT:系统所有入口流量的平均响应时长
  • 线程数:系统所有入口流量的并发线程数
  • 入口QPS:系统所有入口流量的QPS
  • CPU使用率:系统CPU使用率

黑白名单

黑白名单在【授权规则】中配置,需要配置【资源名】和【流控应用】两个配置项,【资源名】就是当前授权规则保护的当前资源,【流控应用】指的是调用方,黑白名单限制的就是调用方法。


集群流控

【集群流控】分两种角色:"Token Client"和"Token Server"。服务作为"Token Client"请求"Token Server"获取token,当获取不到时则进行限流。

我们添加"Token Server"时需要指定【机器类型】:

  • 应用内机器:选择注册到Sentinel上的某个应用所在的机器作为"Token Server"。
  • 外部指定机器:指定一台外部的机器作为"Token Server"。

然后我们可以在【流控规则】中勾选【是否集群】开启集群流控,需要配置【集群阈值模式】:

单机均摊:集群总阈值 = 连接到"Token Server"的"Token Client"数量 * 均摊阈值。

总体阈值:指定的阈值就是集群的总阈值。

相关推荐
海绵波波1071 小时前
flask后端开发(10):问答平台项目结构搭建
后端·python·flask
网络风云2 小时前
【魅力golang】之-反射
开发语言·后端·golang
Q_19284999062 小时前
基于Spring Boot的电影售票系统
java·spring boot·后端
运维&陈同学3 小时前
【Kibana01】企业级日志分析系统ELK之Kibana的安装与介绍
运维·后端·elk·elasticsearch·云原生·自动化·kibana·日志收集
小天努力学java4 小时前
【面试系列】深入浅出 Spring
java·spring·面试
2401_857610036 小时前
中文学习系统:成本效益分析与系统优化
java·数据库·学习·架构
Javatutouhouduan6 小时前
如何系统全面地自学Java语言?
java·后端·程序员·编程·架构师·自学·java八股文
后端转全栈_小伵6 小时前
MySQL外键类型与应用场景总结:优缺点一目了然
数据库·后端·sql·mysql·学习方法
huaqianzkh6 小时前
数据流图和流程图的区别
架构·流程图
time_silence7 小时前
微服务——数据管理与一致性
微服务·云原生·架构