一、为什么要用到sentinel
首先我们要知道的是一个微服务项目如果一个服务挂载掉了,会出现什么情况,是不是回出现一个服务挂载而另一个服务还需要一直调用此服务就很容易导致和它有关联的服务不能被访问到,这也就是我们常常在生活中说到的雪崩效应(因为在雪崩发生时,雪层的一小部分开始滑动,随后带动更多的雪层滑动,最终形成大规模的雪崩),所以如果我们不想到措施可以把这一部分的雪层隔离出去或者进行其他的处理就会导致大规模的系统崩溃。
大家可以根据上面的图片理解一下,服务雪崩是一个什么样子的过程
而sentinel的出现就是为了解决这一问题可以帮我们熔断服务会着帮我们服务降级等等。
在sentinel出现之前一般我们使用到的技术是Hystrix,但是Hystrix是在2020年就停止更新了,而sentinel是springcloudalibaba中使用到的组件,而且现在很多国内的公司也在使用这个组件。我们也可以看一下这两个框架的对比。
特性 | Sentinel | Hystrix |
---|---|---|
语言 | Java | Java |
流量控制 | 支持,包括 QPS 流量控制、并发线程数控制等 | 支持,主要通过线程池和信号量实现流量控制 |
熔断机制 | 支持,提供多种熔断策略(如慢调用比例、异常比例等) | 支持,通过断路器模式实现,主要基于请求失败比例触发熔断 |
系统保护 | 支持,可以监控系统资源(如 CPU、内存)并进行保护 | 不支持,主要关注单个服务的熔断和流量控制 |
热点参数限流 | 支持,可以针对热点参数进行限流 | 不支持,主要关注服务级别的流量控制 |
集群模式 | 支持,可以在多个服务实例之间共享流量控制和熔断状态 | 不支持,主要在单个服务实例内部实现流量控制和熔断 |
配置方式 | 支持动态规则配置,可以通过控制台实时调整 | 支持动态规则配置,但配置方式较为复杂 |
监控与告警 | 提供丰富的监控和告警功能,可以实时监控系统状态并及时通知管理员 | 提供基本的监控功能,但告警功能不如 Sentinel 完善 |
集成方式 | 易于集成,支持 Spring Cloud、Dubbo 等多种框架 | 易于集成,主要与 Netflix 的其他组件(如 Eureka、Zuul)集成 |
社区支持 | 活跃的社区支持,持续更新和优化 | 社区支持较为有限,但有 Netflix 背书 |
二、sentinel的应用场景
1.服务控流
- 目的:控制进入特定服务的流量,防止服务因流量过大而崩溃。
- 实现方式:通过限制每秒处理的请求数(QPS)或并发请求数来实现。例如,可以通过设置阈值来限制一个服务在特定时间内可以处理的请求数量。
- 应用场景:在流量高峰期间,或者在服务需要维护时,通过控制流量来保护服务不被过载。
2.服务熔断
- 目的:当服务出现异常(如响应时间过长或错误率过高)时,自动切断对该服务的调用,防止异常扩散到整个系统。
- 实现方式:通过断路器模式实现。当服务的错误率或响应时间超过预设阈值时,断路器会打开,阻止进一步的请求调用,直到服务恢复正常。
- 应用场景:在服务依赖的服务出现故障时,通过熔断机制保护主服务不受影响。
3.服务降级
- 目的:在服务不可用或响应时间过长时,提供备选的响应或功能,确保系统的可用性。
- 实现方式:通过预定义的降级策略来实现。例如,当一个服务的响应时间超过设定的阈值时,系统可以返回一个默认的响应或跳转到一个降级的服务。
- 应用场景:在服务出现故障或响应时间较长时,通过降级策略提供基本的服务,避免完全的服务中断。
4.热点参数控流
- 目的:针对系统中的热点参数(即请求量特别大的参数)进行流量控制,防止这些参数的请求量过大影响系统性能。
- 实现方式:通过识别和限制对特定参数的请求量来实现。例如,可以为特定的 API 参数设置请求阈值,当请求量超过这个阈值时,系统会拒绝额外的请求或进行限流。
- 应用场景:在某些参数的请求量异常高时,通过热点参数控流来保护系统不被这些请求所影响。
三、sentinel安装以及基本使用
1.安装
这个地方我给出 spingcloudalibaba对应组建的版本,有需要的也可以去官网再自己查看对应版本
版本发布说明 - Spring Cloud Alibaba官网 (aliyun.com)
所以我选择的版本是1.8.5
下载其实我们可以看到sentinel就是一个jar包我们可以直接用java -jar的方式启动,当然我们也可以通过-Dserver.port=8858指定端口号
java -jar sentinel-dashboard-1.8.5.jar
浏览器访问sentinel Sentinel Dashboard,初始用户名和密码均为sentinel
2.使用
第一步:引入maven依赖到pom.xml文件中
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
第二步:编写application.properties文件,在文件中指出sentinel服务器的端口地址
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8858
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
spring.cloud.sentinel.eager=true
# 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
# spring.cloud.sentinel.transport.client-ip=
# 应用服务 WEB 访问端口
server.port=8859
第三步:编写一个请求方法,并且使用@SentinelResource 注解用来标识资源是否被限流、降级。
package com.ltx.sentineldemo.demos.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping(value = "/hello")
@SentinelResource("hello")
public String hello() {
return "Hello Sentinel";
}
}
第四步:测试,这个地方我们不一定一启动就就会把我们的hello方法配置到 sentinel控制台中可能需要我们自己先去访问一下hello请求才可以帮我们动态的加入到 sentinel控制台中,结果如下图所示:
3.用程序的方式来编写hello方法的流量控制
首先我们使用代码硬编码的方式来定义流量控制规则,并且使用@PostConstruct在服务启动前进行初始化。
//定义了每秒最多接收3个请求
@PostConstruct
private static void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule("hello");
rule.setCount(3);
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
编写一个简单的流量控制流控后的处理方法以及异常后的处理方法
package com.ltx.sentineldemo.demos.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
/**
* 测试sentinel
* blockHandler设置默认的流控后的处理方法
* fallback设置默认的异常后的处理方法
* @return
*/
@GetMapping(value = "/hello")
@SentinelResource(value = "hello",blockHandler = "helloBlockHandler",fallback = "helloFallback")
public String hello() {
return "Hello Sentinel";
}
public String helloBlockHandler(BlockException e) {
return "流控";
}
public String helloFallback(Throwable t) {
return "出现异常";
}
}
我们可以去 sentinel控制台看一下是否配置了规则到sentinel中
然后我们去访问一下hello接口,流控方法处理成功
然后我直接在hello方法中写下异常的代码1/0结果如下所示:
4. 使用控制台配置
点击流控
1)流控参数
流控效果:
快速失败:这种策略适用于那些对响应时间有严格要求的业务场景。通过快速失败,系统可以迅速释放资源,避免在处理慢请求时占用过多资源,影响其他请求的处理。
Warmup(预热):预热机制特别适用于系统启动或流量突增时的场景。通过预热,系统可以逐步增加流量,避免因流量突变而对系统造成冲击。这有助于平滑流量波动,提高系统的稳定性。
排队等待:排队等待机制适用于那些需要处理大量并发请求的业务场景。通过排队,系统可以有序地处理请求,避免因并发请求过多而导致的服务崩溃。这种机制可以平衡请求的处理速度和系统资源的使用,提高系统的可用性。
流控模式:
直接流量控制:直接限制单位时间内的请求数量,例如每秒的请求数(QPS)。适用于需要限制整体流量的场景,如限制对数据库的访问频率。
关联流量控制:根据关联资源的访问情况来控制流量,例如限制对某个服务的访问。适用于需要根据服务调用链路来控制流量的场景,防止某个服务因调用过多而崩溃。
链路流量控制:限制某个特定链路的流量,防止链路中的资源过载。适用于需要保护特定调用链路的场景,如保护关键服务不被过载。
2)熔断参数
3)热点配置
然后在新增后就可以进行高级配置了,我们可以选择参数的类型和参数对应的值去限制
四、sentinel整合openfegin
第一步:引入maven依赖到pom.xml文件
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
第二步:编写fallback实现类实现fegin连接器接口
package com.ltx.nacosconsumer.demos.clients;
public class ConsumerClientFallBack implements ConsumerClient{
@Override
public String test() {
return "服务降级了";
}
}
第三步:开启注解
package com.ltx.nacosconsumer.demos.clients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name ="provider",fallback = ConsumerClientFallBack.class)
public interface ConsumerClient {
@GetMapping(value = "/t")
String test();
}
第四步:在配置文件中打开Feign支持sentienl
feign.sentinel.enabled=true