面对互联网的高并发过载流量,为了保证系统的稳定性,我们一般会对过载流量进行限流。今天就给大家详细介绍一款限流框架
1、什么是 sentinel:
在基于 SpringCloud 构建的微服务体系中,服务间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素。
在并发流量比较高的情况下,由于网络调用之间存在一定的超时时间,链路中的某个服务出现宕机都会大大增加整个调用链路的响应时间,而瞬间的流量洪峰则会导致这条链路上所有服务的可用线程资源被打满,从而造成整体服务的不可用,这也就是我们常说的 “雪崩效应”。
而在微服务系统设计的过程中,为了应对这样的糟糕情况,最常用的手段就是进行 ”流量控制“ 以及对网络服务的调用实现“熔断降级”。因此,Sentinel 就因运而生了。
Sentinel 是一款面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来保障服务的稳定性,核心思想是:根据对应资源配置的规则来为资源执行相应的流控/降级/系统保护策略,Sentinel 的主要特性如下图:
2、主流限流熔断组件对比:
从三者的对比来看,Hystrix 功能相对较少且官方已宣布停止维护,官方推荐 resilience4j 作为 Hystrix 的替代品。而对比 resilience4j 和 sentinel,可明显看出 sentinel 支持的功能、场景更丰富,灵活性可用性更高。
3、sentinel-dashboard 控制台的部署与使用说明:
(1)进入官网下载 sentinel-dashboard 的 jar 包:Releases · alibaba/Sentinel · GitHub
(2)使用以下命令直接运行 jar 包(JDK 版本必须≥ 1.8):
java -jar -Dserver.port=9999 sentinel-dashboard-1.8.2.jar
(3)启动参数说明:
-
-Dserver.port
:指定启动的端口,默认8080 -
-Dproject.name
:指定本服务的名称 -
-Dcsp.sentinel.dashboard.server
:指定sentinel控制台的地址,用于将自己注册进入实现监控自己 -
-Dsentinel.dashboard.auth.username=sentinel
用于指定控制台的登录用户名为 "sentinel",默认值为 “sentinel” -
-Dsentinel.dashboard.auth.password=123456
用于指定控制台的登录密码为 "123456",默认值为 "sentinel" -
-Dserver.servlet.session.timeout=7200
用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟,需要注意的是,部署多台控制台时,session 默认不会在各实例之间共享,这一块需要自行改造。
更多具体启动参数配置如下图:
官方文档地址:https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
(4)控制台访问地址:http://localhost:9999
,默认账号密码都为sentinel/sentinel
二、SpringBoot 整合 sentinel-dashboard
接下来我们介绍下 SpringBoot 集成 sentinel-dashboard
控制台进行规则配置。那为什么要集成 sentinel-dashboard
控制台,sentinel 不是提供了相关的API吗?
其实 SpringBoot 官方一直提倡 约定>配置>编码
的规则,能够不硬编码何乐而不为呢?因此本文后续内容主要还是结合 sentinel-dashboard
控制台进行讲解,关于API的使用大家可以按照官方文档学习,讲解的非常清楚,这里就不过多介绍了。
1、引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、添加配置:
# sentinel看板的地址
spring.cloud.sentinel.transport.dashboard = localhost:9999
# 开启对sentinel看板的饥饿式加载。sentinel默认是懒加载机制,只有访问过一次的资源才会被监控,通过关闭懒加载,在项目启动时就连接sentinel控制台
spring.cloud.sentinel.eager = true
3、新建测试接口:
@RestController
@RequestMapping("/sentinel")
public class FlowLimitController {
@GetMapping("/test")
public String test(){
return "接收到一条消息--------";
}
}
4、启动微服务:
启动微服务,然后浏览器输入:http://localhost:9999/sentinel/test
,此时查看sentinel控制台,将会看见 sentinel-service
这个服务已经被监控了,如下图:
三、Sentinel-dashboard的使用与规则配置
前面我们基于 SpringBoot 整合了 Sentinel-dashboard
,这一部分我们就详细介绍下sentinel-dashboard
控制台的使用。
1、资源与规则:
Sentinel
可以简单分为 Sentinel
核心库和 Dashboard
,核心库不依赖 Dashboard
,但是结合 Dashboard
可以获得更好的效果。使用 Sentinel
来进行资源保护,主要分为几个步骤:
(1)定义资源: 资源可以是程序中的任何内容,例如一个服务,服务里的方法,甚至是一段代码。
(2)定义规则: Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点参数规则。
(3)检验规则是否生效
由于 Sentinel 中所有的规则都可以在动态地查询和修改,并且修改后立即生效,并且 Sentinel 中资源定义和规则的配置是分离的。因此在编码时,我们先把需要保护的资源定义好(埋点),之后便可以在需要的时候动态配置规则了。也可以理解为,只要有了资源,我们就能在任何时候灵活地定义各种规则。
1.1、定义资源:
对于资源的定义有两种,一种是硬编码的方式,一种是通过 @SentinelResource
注解的方式。
(1)硬编码方式(不推荐):
但由于硬编码的方式对代码的侵入性太强,不推荐使用,所以我们在下文只简单介绍下了如何使用
① 抛出异常的方式定义资源:SphU
使用 SphU.entry(“资源名”)
定义资源的方式主要用于 try-catch
,将需要保护的代码使用 SphU.entry("资源名")
和 entry.exit()
包围起来,当 catch 到 BlockException
时执行异常处理
代码示例:
Entry entry = null;
try {
// 定义一个sentinel保护的资源,
entry = SphU.entry(resourceName);
// 被保护的业务逻辑
} catch (BlockException e) {
// 如果被保护的资源被限流或者降级了,就会抛出BlockException
log.warn("资源被限流或降级了", e);
} catch (InterruptedException e) {
log.error("发生InterruptedException",e);
} finally {
if (entry != null) {
entry.exit();
}
}
在下面的例子中, 用 try-with-resources
来定义资源。参考代码如下:
public static void main(String[] args) {
// 配置规则.
initFlowRules();
// 1.5.0 版本开始可以直接利用 try-with-resources 特性
try (Entry entry = SphU.entry(resourceName)) {
// 被保护的逻辑
System.out.println("hello world");
} catch (BlockException ex) {
// 处理被流控的逻辑
System.out.println("blocked!");
}
}
② 返回布尔值的方式定义资源:
使用 SphO.entry(“资源名”)
定义资源的方式主要用于 if-else
,当资源发生触发 sentinel
规则之后就会返回 false,这时可以根据返回值,进行限流降级的处理逻辑。