目录
一、Sentinel 介绍
1.1 什么是 Sentinel
- Sentinel 对开发者的大概印象应该是阿里开源的一个SpringCloud 组件,用来做微服务的限流、降级和熔断。这也是本文从概念和实战上主要的展开点。
- 官方点的话说就是: Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。
1.2 Sentinel 特性
官方总结了 Sentinel 组件的4大特性,概括了 Sentinel 组件提供的能力:
- 丰富的应用场景:阿里巴巴 10 年双十一积累的丰富流量场景,包括秒杀、双十一零点持续洪峰、热点商品探测、预热、消息队列削峰填谷等多样化的场景;
- 易于使用,快速接入:简单易用,开源生态广泛,针对 Dubbo、Spring Cloud、gRPC、Zuul、Reactor、Quarkus 等框架只需要引入适配模块即可快速接入;
- 多样化的流量控制:资源粒度、调用关系、指标类型、控制效果等多维度的流量控制;
- 可视化的监控和规则管理:简单易用的 Sentinel 控制台;
1.3 限流、降级与熔断的区别
- 限流是在流量进入到系统内之前,先进行一个统计计算,如果已经超过设定的阈值,则直接拒绝当前的请求,那么当前流量不会进入服务的内部;
- 降级指的是如果在执行一个请求的调用时,如果发生了异常,那么请求就会继续执行指定的降级逻辑。此时,请求已经进入到了服务内部;
- 熔断是对一个时间窗口内处理的请求的结果进行统计后,如果这批请求的错误率达到了阈值(或者慢接口比例达到了阈值),则会触发一个指定时间段长度的熔断;
服务的限流、降级、熔断这三板斧的结合在很大程度上抑制了服务雪崩的发生。
二、实战演示
2.1 下载启动 Sentinel 控制台
我们到 Sentinel 官方的 Github 上下载 sentinel-dashboard 服务的 Jar 包,Sentinel 服务的限流、熔断等规则的下发就是通过 sentinel-dashboard 来进行的,下载链接。当前的最新版本是1.8.7。
sentinel-dashboard 的 Jar 包下载完毕后,把它放在合适的目录,使用如下命令启动Jar包:
java -Dserver.port=8888 -Dcsp.sentinel.dashboard.server=localhost:8888 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar
然后在浏览器的地址框内输入 http://localhost:8888/
会进入 Sentinel 控制台的登陆界面:
默认的用户名和密码都是 sentinel
,输入后即可进入 Sentinel 控制台主界面:
2.2 后端微服务接入 Sentinel 控制台
2.2.1 引入 Sentinel 依赖
在我们需要使用 Sentinel 组件的后端微服务中先引入 Sentinel 的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.2.2 添加 Sentinel 连接配置
如果要想将后端微服务对接到 Sentinel 控制台,除了要添加 Sentinel 依赖以外,还需要在配置文件中添加上 Sentinel 控制台相关的配置信息,主要是为了配置Sentinel 控制台的访问地址,此处配置的本地访问端口号为8888。
spring:
cloud:
sentinel:
transport:
# sentinel 的默认端口号为 8719
port: 8719
# dashboard地址
dashboard: localhost:8888
2.3 使用 Sentinel 进行流控(含限流)
2.3.1 对接口添加 Sentinel 资源标记
对于 Sentinel 组件来说,一切的 API 接口都是资源,Sentinel 的职责就是在流量到来时,根据这些 Sentinel 资源的负载情况对流量进行管理。所以,我们需要先对代码中定义的 API 接口打上 Sentinel 资源的标记。Sentinel 是通过 @SentinelResource
注解对 API 接口打标记的。下面以2个获取商品的接口为例演示下用法。
@GetMapping("/getGoods")
@SentinelResource(value = "getGoods")
public CoinGoodsInfo getGoods(@RequestParam("id") Long id){
log.info("Get goods, id={}"