1. 概述
Sentinel是阿里开源的一套用于服务容错的综合性解决方案,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。 Sentinel具有以下特性:
- 丰富的应用场景
- 完备的实时监控
- 广泛的开源生态
- 完善的SPI扩展点
Sentinel架构如下图所示: Sentinel 分为两个部分: 核心库(Java 客户端):不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。 控制台(Dashboard):基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
2. 安装Sentinel控制台
在官网下载最新的Sentinel控制台程序,目前最新版本是1.8.4,JDK最低为1.8,Sentinel默认使用端口为8080,使用命令java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar 启动控制台程序,默认用户名和密码都是sentinel
3. 开发Sentinel微服务
3.1. 引入核心依赖
新建SpringBoot项目,引入核心依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
3.2. application.yml配置文件
server:
port: 8300
spring:
application:
name: alibaba-sentinel
cloud:
nacos:
discovery:
server-addr: xx.xx.xx.xx:8848
username: nacos
password: nacos
sentinel:
transport:
dashboard: xx.xx.xx.xx:8080
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
3.3. 主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelApplication.class, args);
}
}
3.4. controller类
@RestController
@RequestMapping("/sentinel")
public class SentinelController {
@GetMapping("/getSentinelInfo")
public String getSentinelInfo() {
return "This is sentinel info,now is " + LocalDateTime.now();
}
@GetMapping("/getSentinelDetails")
public String getSentinelDetails() {
return "This is sentinel details,now is " + LocalDateTime.now();
}
}
启动Sentinel微服务,查看Sentienl控制台并没有发现Sentinel微服务的接口,由于Sentinel采用的是懒加载方式,需要先执行一次接口访问
3.5. 几个基本概念和功能
资源:就是Sentinel要保护的东西,可以是Java应用程序中的任何内容,可以是一个服务,也可以是一个方法,甚至可以是一段代码 规则:用来定义如何进行保护资源的,作用在资源之上,定义以什么样的方式来保护资源,主要包括流量控制规则、熔断降级规则以及系统保护规则 流量控制:用于调整网络包的数据,任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的,需要根据系统的处理能力对流量进行控制 熔断降级:当检测到调用链路中某个资源出现不稳定的表现,如请求响应时间长或异常比例升高时,则对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联故障。Sentinel通过并发线程数进行限制和通过响应时间对资源进行降级 系统负载保护:Sentinel同时提供系统维度的自适应保护能力,当系统负载较高时,如果还持续让请求进入可能会导致系统崩溃,无法响应,在集群环境下,会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求
4. 流控规则
流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性 点击簇点链路,可以看到访问过的接口,在接口的操作中点击流控 或者点击流控规则,再点击新增流控规则 新增流控规则 资源名:唯一名称,默认请求路径 针对来源:Sentinel可以针对调用者进行限流,填写微服务名称,默认default(不区分来源) 阈值类型/单机阈值: ?QPS(每秒请求量):当调用该api的QPS达到阈值的时候,进行限流 ?线程数:当调用该api的线程数达到阈值的时候,进行限流 是否集群:不需要集群
4.1. 流控模式
流控模式: ?直接:api达到限流条件时,直接限流 ?关联:当关联的资源达到阈值时,就限流自己 ?链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流),api级别的针对来源
4.1.1. 直接流控模式
当指定的接口达到限流条件时开启限流
4.1.2. 关联流控模式
使用jmeter调用接口/sentinel/getSentinelDetails测试,QPS大于配置的单机阈值 再次访问接口/sentinel/getSentinelInfo,会发现已经被限流
4.1.3. 链路流控模式
当从某个接口过来的资源达到限流条件时,开启限流,与针对来源配置项的区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,粒度更细
4.2. 流控效果
流控效果: ?快速失败:直接失败,抛异常 ?Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值 ?排队等待:均速排队,让请求以均速的速度通过,阈值类型必须设置为QPS,否则无效
5. 熔断规则
Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException) 左侧点击簇点链路,选择接口,在接口后面点击熔断 或者点击熔断规则,再点击新增熔断规则 进入新增熔断规则界面
5.1. 慢调用比例
即平均响应时间,当1S内持续进入n个请求,对应时刻的平均响应时间(秒级)均超过阈值(ms),那么在接下来的时间窗口之内,对这个方法的调用都会自动熔断,RT默认最大值为4900ms,超出此阈值都会算作4900ms
5.2. 异常比例
当资源每秒请求量>=n,并且每秒异常总数通过量的比值超过阈值之后,资源进入降级状态,即在接下来的时间窗口之内,对这个方法的调用都会自动地返回,异常比率的阈值范围是[0.0,1.0],代表0% - 100%
5.3. 异常数
当资源近1分钟的异常数目超过阈值之后会进行熔断,由于统计的时间窗口是分钟级别的,若timeWindow小于60s,则结束熔断状态后仍可能再进入熔断状态
6. 热点规则
热点即经常访问的数据,很多时候希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其他操作,允许将规则具体到参数上 后端controller代码为:
@GetMapping("/getSentinelInfoByIdAndName")
@SentinelResource(value = "sentinelInfoByIdAndName")
public String getSentinelInfoByIdAndName(@RequestParam(value = "id", required = false) Long id, @RequestParam(value = "name", required = false) String name) {
return "This is sentinel info for id:" + id + " and name:" + name;
}
在浏览器输入地址http://localhost:8300/sentinel/getSentinelInfoByIdAndName?id=1,多次刷新请求,可以看到异常 在浏览器输入地址http://localhost:8300/sentinel/getSentinelInfoByIdAndName?name=zhangsan,多次刷新请求,不会发生异常 参数例外项允许对一个参数的具体值进行流控,编辑定义的规则,增加参数例外项 配置异常处理,后端代码如下:
@GetMapping("/getSentinelInfoByIdAndName")
@SentinelResource(value = "sentinelInfoByIdAndName", blockHandler = "dealHandler")
public String getSentinelInfoByIdAndName(@RequestParam(value = "id", required = false) Long id, @RequestParam(value = "name", required = false) String name) {
return "This is sentinel info for id:" + id + " and name:" + name;
}
public String dealHandler(Long id, String name, BlockException exception) {
return "The interface is current-limited, request parameters is id:" + id + " name:" + name + "exception is:" + exception;
}
再次调用接口
7. 系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU使用率、平均RT、入口QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。 系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量,比如Web服务或Dubbo服务端接收的请求,都属于入口流量。 系统规则有如下模式 Load自适应:系统的load1作为启发指标,进行自适应系统保护,当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR阶段),系统容量由系统maxOps * minRt估算得出,设定参考值一般是CPU cores * 2.5 CPU usage:当系统CPU使用率超过阈值即触发系统保护(0.0 - 1.0),比较灵敏 平均RT:当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位毫秒 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护 入口QPS:当单台机器上所有入口流量的QPS达到阈值即触发系统保护
8. 授权规则
很多时候,需要根据调用来源来判断该次请求是否允许放行,这时候可以使用Sentinel的来源访问控制的功能,来源访问控制根据资源的请求来源限制资源是否通过 若配置白名单,则只有请求来源位于白名单内的才可通过 若配置黑名单,则请求来源位于黑名单时不通过,其他的请求通过
9. 整合OpenFeign
9.1. 引入核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
9.2. application.yml配置
feign:
sentinel:
enabled: true
9.3. Feign接口
@FeignClient(value = "alibaba-service-provider", fallback = ProviderServiceFallback.class)
public interface ProviderService {
@GetMapping("/service/getServiceInfo")
String getServiceInfo();
}
9.4. 容错处理类
@Component
public class ProviderServiceFallback implements ProviderService {
@Override
public String getServiceInfo() {
return "Service downgraded, please try again later!";
}
}
9.5. controller层实现
@Resource
private ProviderService providerService;
@GetMapping("/getProviderInfo")
public String getProviderInfo() {
String serviceInfo = providerService.getServiceInfo();
return "This is provider service info:" + serviceInfo;
}
9.6. 验证
启动服务提供服务和Sentinel服务 在Sentinel控制台配置流控规则 注意选择上图方法,配置流控规则 浏览器输入地址http://localhost:8300/sentinel/getProviderInfo,多次刷新
10. 规则持久化
上面的配置存在一个问题,一旦我们重启应用,sentinel规则将消失,因此需要将限流配置规则持久化进Nacos保存,只要刷新服务提供微服务某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对服务提供微服务上sentinel上的流控规则持续有效
10.1. 引入核心依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
10.2. application.yml配置
spring:
sentinel:
datasource:
ds:
nacos:
server-addr: xx.xx.xx.xx:8848
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
10.3. nacos业务规则配置
resource:资源名称; limitApp:来源应用; grade:阈值类型,0表示线程数,1表示QPS; count:单机阈值; strategy:流控模式,0表示直接,1表示关联,2表示链路; controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
10.4. 验证
启动sentinel微服务,刷新Sentinel控制台即可
|