1.什么是Sentinel?
Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。
2012 年,Sentinel 诞生,主要功能是提供请求流量控制;
2013-2017 年,Sentinel在阿里巴巴集团内部大量用于生产实践,成为基础技术模块,覆盖了所有的核心场景;
2018 年,Sentinel 对外开源,并持续演进和版本迭代。
Sentinel在经过阿里巴巴内部一系列秒杀大促,特别是双11这样电商大促中的锤炼,目前已有不少企业在使用开源版本和云版本的Sentinel,包括顺丰、vivo、每日优鲜、拼多多、易企秀、爱奇艺、融金所、VIPKID、喜马拉雅FM、百融金服等;
更多使用者:https://github.com/alibaba/Sentinel/issues/18
按照官方的定义:
A lightweight powerful flow control component enabling reliability and monitoring for microservices.
轻量级的流量控制、熔断降级Java 组件,是分布式系统的流量防卫兵;
Github:https://github.com/alibaba/Sentinel
2.Sentinel主要组成
- 核心库(Java 客户端):Sentinel的核心库不依赖任何第三方框架/库,能够运行于所有 Java环境,同时对 Dubbo / SpringBoot / Spring Cloud 等框架也有很好的支持;
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器;.
3.在项目中使用Sentinel进行限流
1.下载Sentineljar包启动Dashboard。
java -jar .\sentinel-dashboard-1.8.2.jar
默认端口为8080
启动成功后访问Sentinel控制台。localhost:8080。默认账号密码都是sentinel。可以在jar包中修改。
2. 在项目中添加依赖
<!-- 加入sentinel流量监控 -->
<!--spring-cloud-starter-alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
3.添加配置信息在application.yml中
spring:
application:
name: consumer
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
- 启动服务访问任意接口即可在Sentinel控制台看到资源路径,并设置限流、降级等保护规则。
- 我们可以通过访问http://{微服务注册的ip地址}:8719/api接口查看微服务暴露给Sentinel控制台调用的API列表;比如访问:http://localhost:8719/api
4Sentinel设置保护规则
在簇点链路界面支持设置四种保护规则:流控、熔断降级、热点控制、服务访问授权。
4.1. 流量控制
资源名:访问的路径
针对来源:来自那个服务的请求,默认所有。
阈值类型:QPS或线程数
单机阈值:单节点的阈值。
是否集群:被请求的服务是否是集群部署。
流控模式:
直接:就是直接对资源进行流控,对资源自身的QPS或访问线程数进行控制。
关联:如果关联的对象达到流控标准则限制本资源访问。
链路:记录指定链路上的流量?
流控效果:
快速失败:直接失败
Warm Up:根据coldFactor(默认为3),从阈值/coldFactor,经过预热的时长才达到QPS阈值。比如阈值为100。100/3=33,用33作为初始值在预热时长内到达阈值则开始限流。
排队等待:在QPS到达阈值后,新的请求就等待,直到超时。可以适用于突发流量激增的场景。
4.1熔断降级
熔断策略
1.慢调用比例:平均响应时间 (DEGRADE_GRADE_RT),当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException),注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置;
2.异常比例:异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO)是指当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回,异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%;
3.异常数:异常数 (DEGRADE_GRADE_EXCEPTION_COUNT)是指当资源近1分钟的异常数目超过阈值之后会进行熔断,注意由于统计时间窗口是分钟级别的,若timeWindow小于 60s,则结束熔断状态后仍可能再进入熔断状态;
4.2 热点规则
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流,热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效;
某个参数过热:单位时间内达到阈值,就会被降级。
- 热点规则不能直接对controller中的路径生效,需要配合SentinelResource注解配合使用
@GetMapping("/name") @SentinelResource("app") public String getName(String app){ return name+":"+age+":" +addr+":" +sex+":"+app; }
可以设置特殊参数,针对该值独立的设置阈值。仅支持基本类型
下图可以看出参数值为aoe时通过QPS为5,值为其他时QPS仅有2。
4.3系统保护规则
Load,Load自适应(仅对Linux/Unix-like机器生效):系统的load1作为启发指标,进行自适应系统保护,当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护,系统容量由系统的maxQps * minRt估算得出,设定参考值一般是 CPU cores * 2.5;
平均 RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒;
并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护;
入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护;
CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏;
4.4授权规则
权限控制一般放在网关做了,不再赘述。
5.Sentinel通信原理
6.Spring Cloud Aliababa Sentinel三种保护应用方式。
6.1直接拦截所有的Controller请求路径
Sentinel为springboot程序提供了一个starter依赖,由于sentinel starter依赖默认情况下就会为所有的HTTP服务提供限流埋点,所以在springboot 中的Controller都可以受到Sentinel的保护;
只需为应用添加 spring-cloud-starter-alibaba-sentinel依赖,所有的HTTP接口都能获得Sentinel保护,当然,我们还需要为Sentinel配置保护的规则;
底层通过一个拦截器对请求url进行拦截:
com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor
可以通过配置关闭Sentinel对Controller的保护:
#关闭sentinel对controller的url的保护
spring.cloud.sentinel.filter.enabled=false
6.2编写代码保护应用,侵入较强
@GetMapping("/test3/{app}")
public String test3(@PathVariable("app") String app) {
System.out.println("/test3/{app} --> " + app);
Entry entry = null;
try {
entry = SphU.entry("test3");
return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
} catch (BlockException e) {
e.printStackTrace();
return "熔断降级了...";
} finally {
if (entry != null) {
entry.exit();
}
}
}
6.3通过注解@SentinelResource的参数值来保护应用。
7.开启Sentinel对RestTemplat的支持
- 设置配置项
#true开启sentinel对resttemplate的支持,false则关闭
resttemplate.sentinel.enabled=true
- 编写代码
//配置降级和限流处理器
@SentinelRestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
这里配置限流和降级方法到注解中一直报错,晚上再看看。
配置的限流阈值是针对集群内所有机器限制的。如下:QPS阈值为3
服务1:
服务2:
第四次访问:
8.开启Sentinel对Feign支持
- 开启对feign的支持配置
#true开启sentinel对feign的支持,false则关闭
feign.sentinel.enabled=true
- 编写代码
在feign注解配置降级类,尽量使用fallbackFactory进行降级,可以对异常进行处理
@FeignClient(name = "producer",fallbackFactory = FeignClientServiceFallbackFactory.class,configuration = FeignConfiguration.class)
public interface FeignClientService
{
@GetMapping("v1/producer/get_username")
String getName();
}
编写降级工厂类
import com.alan.nacos.common.FeignClientService;
import feign.hystrix.FallbackFactory;
public class FeignClientServiceFallbackFactory implements FallbackFactory<FeignClientService>
{
@Override
public FeignClientService create(Throwable throwable) {
return new FeignClientService() {
@Override
public String getName() {
System.out.println("服务降级了!");
return "服务降级了";
}
};
}
}
Sentinel降级条件配置
限流效果:
9.流控规则持久化到Nacos
暂时仅支持启动项目时从Nacos读取配置,不支持设置配置更新到Nacos
- 添加依赖
<!--sentinel数据持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- 配置nacos读取文件
spring:
application:
name: consumer
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
datasource:
ds1:
nacos:
server-addr: 192.168.144.100:80
data-id: consumer.json
group-id: DEFAULT_GROUP
data-type: json
rule-type: flow
- nacos配置流控规则
4.启动服务后刷新请求即可看到流控规则已经生效。
10.自定义限流及降级返回信息。
- 降级流控方法参数和返回值要和被保护方法一致,并增加BlockException 异常参数。
public class MyBlockHandlerClass
{
/**
* 该方法一定要是static方法
*
* @param aaa
* @return
*/
public static String block(String aaa, BlockException e){
System.out.println(aaa);
return "Block Handler";
}
@GetMapping("/name")
@SentinelResource(value = "app",blockHandler = "block",blockHandlerClass = MyBlockHandlerClass.class)
public String getName(String app){
return name+":"+age+":" +addr+":" +sex+":"+app;
}