Sentinel 入门应用
一、概述
Sentinel 是阿里中间件团队开源的,面向分布式服务架构的轻量级高可用流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助用户保护服务的稳定性。
二、限流的作用
- 保护系统避免被瞬时流量冲垮
- 预防恶意请求
- 针对请求进行限制
- 服务器
- 应用(接口的处理能力(QPS/TPS))。RT ->Jmeter(压测)
- 资源限制(cpu、线程池、内存、网络资源)
- 如何控制流量
- 限流的指标(可以容纳的流量、已经容纳的流量、可以接受的流量) 阈值
- 限流的过程(通过算法来实现)
- 限流的结果(处理策略)
- 分布式限流
Redis - Lua实现令牌桶 ( Redisson)、Zookeeper
限流(流量控制)是指系统在面临高并发,或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的稳定性。但是限流会导致部分用户请求处理不及时或者被拒,影响了用户体验。所以还是要根据业务的实际情况平衡一下。
三、限流的算法
1、固定窗口限流算法(计数器), 将单位时间段当做一个窗口,计数器记录这个窗口接收请求的次数。但是有一个很明显的临界问题。
解决方式:总的并发数、线程池大小,连接数大小以及滑动窗口限流算法
2、滑动窗口限流算法,将单位时间周期分为n个小周期,分别记录每个小周期内接口的访问次数,并且根据时间滑动删除过期的小周期。虽然解决了固定窗口的临界问题,但是一旦到达限流后,请求都会直接暴力被拒绝。这样会损失一部分请求,这其实对于产品来说,并不太友好。
3、漏桶算法,漏桶算法面对限流,就更加的柔性,不存在直接的粗暴拒绝
- 流入的水滴,即访问系统的请求,这个流入速率是不确定的。
- 桶的大小是固定的,表示系统所能处理的请求数。
- 如果桶的容量满了,就达到限流的阀值,就会丢弃水滴(拒绝请求)
- 水的流出速度是固定的,对应服务按照固定的速率处理请求
但是面对突发流量的时候,漏桶算法还是固定的速率处理请求,就不是我们想要的结果。流量变突发时,肯定希望系统尽量快点处理请求,提升用户体验。
4、令牌桶算法
面对突发流量的时候, 使用令牌桶算法限流。
- 根据限流大小,定速往令牌桶里放令牌。
- 如果令牌数量满了,超过令牌桶容量的限制,那就丢弃。
- 系统在接受到一个用户请求时,都会先去令牌桶拿一个令牌。如果拿到令牌,那么就处理这个请求的业务逻辑;拿不到令牌,就直接拒绝这个请求。
Guava的RateLimiter限流组件,就是基于令牌桶算法实现的
四、Sentinel 限流使用
Sentinel的核心概念
- 资源(针对谁去限流), 服务、 接口、 方法、 链路。
- 规则(限流的判断规则),总的并发数量? 并发线程数量?
流量控制之后的处理方法:- 抛异常
- 排队
- 降级…
4.1、Sentinel dashboard控制台安装
- 下载sentinel-dashboard-1.8.0.jar
- 在cmd中运行下面的命令
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -
Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
更多参数官网查看
- 访问http://localhost:8080,输入sentinel/sentinel帐号密码即可访问。
4.2、具体实现代码
Sentinel集成到Spring Cloud中,其实本质上是一样的,都是基于Sentinel-Core来完成
流量控制等功能。而且步骤都是一致的
- 第一步写pom(依赖)
- 第二步写配置(yaml、config)或者SPI扩展
- 第三步写注解(使用)
注意版本问题
- Spring Boot版本为2.3.13.RELEASE;
- spring Cloud Alibaba版本为:2.2.6.RELEASE;
- Spring Cloud版本为: Hoxton.SR12。
1、pom添加jar包依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、第二步写配置(yaml、config)或者SPI扩展,在META-INF/services/com.alibaba.csp.sentinel.init.InitFunc文件中,添
加自定义扩展点的全路径
public class FlowRuleInitFunc implements InitFunc {
@Override
public void init() throws Exception {
List<FlowRule> rules=new ArrayList<>();
FlowRule rule=new FlowRule();
rule.setResource("doTest");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(2);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
3、写注解(使用)
@RestController
public class SentinelController {
@Autowired
TestService testService;
@GetMapping("/hi")
public String doTest(){
return testService.doTest();
}
}
@Service
public class TestService {
@SentinelResource(value = "doTest",blockHandler = "handerException")
public String doTest(){
return "Hello,"+new Date();
}
public String handerException(BlockException e){
return "被限流了";
}
}
按照上述步骤配置,即可完成Spring Cloud的整合。Spring Cloud生态下集成的实现其实都差不多,除了Jar包
依赖有差异。在Sentinel官网都有详细说明。