sentinel
- Sentinel提供的各种规则的简单说明
- 01,流量控制
- 一,流控规则(阈值类型:QPS)
- 二,流控规则(阈值类型:并发线程数)
- 三,高级选项
- 02,熔断降级
- 一,概念
- 二,熔断策略
- 三,代码示例
- 01 慢调用熔断
- 02 异常数熔断
- 03 异常比率熔断
- 02,热点规则
- 一,热点规则
- 二,高级选项
- 03,授权规则
Sentinel提供的各种规则的简单说明
下面是Sentinel提供的各种规则的简单说明:
-
流控规则:通过限制每秒钟请求的数量、并发请求的数量、以及根据目标方法的响应时间等方式,限制应用程序的流量。它可以是针对单个API,也可以是整个应用程序。
-
熔断规则:熔断规则是一种保护机制,当应用程序连续几次失败时,它会被强制断开连接以保护应用程序免受进一步损害。熔断规则可以定义触发熔断的失败次数限制、熔断时长、恢复时间等。
-
热点规则:热点规则是指在极端情况下出现的热点数据,可以通过限制被请求最多的资源或者是方法,避免出现线程堆积或者是请求被延迟的现象。
-
系统规则:系统规则用于限制整个应用程序的系统负载以及运行参数,例如CPU的使用率、内存的使用率、磁盘的使用率等等。
-
授权规则:授权规则用于对API进行授权,只允许授权的用户或应用程序进行访问。
01,流量控制
一,流控规则(阈值类型:QPS)
以下是在项目中使用Sentinel的流控规则(阈值类型:QPS)的步骤。
- 添加Sentinel的依赖
在pom.xml文件中添加以下依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 添加配置文件
在application.yml文件中添加以下配置:
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel控制台的地址,用于上报应用的统计信息
port: 8719 # Sentinel的默认端口号
- 使用Sentinel
在需要进行流量控制的方法上使用@SentinelResource注解,示例如下:
@GetMapping("/test")
@SentinelResource(value = "test", blockHandler = "handleBlock")
public String test() {
return "Hello Sentinel!";
}
// 定义 blockHandler 处理请求被限流的情况
public String handleBlock(BlockException ex) {
// 返回请求被限流的提示信息
return "Oops, request is blocked!";
}
- 配置规则
在Sentinel控制台中配置需要的规则,比如流量控制、熔断降级等。具体配置方式可以参考Sentinel的官方文档。
接下来,我们在Sentinel的控制台中配置一个流控规则。具体步骤如下:
-
进入Sentinel的控制台,点击“流量控制”,然后点击“规则管理”。
-
点击“新增流量规则”按钮,创建一个新的流控规则,设置如下参数:
- 阈值类型:QPS
- 需要保护的资源:test
- 单机阈值:1
- 点击“新增”按钮,保存创建的规则。
然后我们就可以通过不断访问“/test”接口来测试这个流控规则。访问次数超过1次/秒时,Sentinel会拦截请求并调用我们刚刚定义的“handleBlock”方法返回限流的提示信息。
二,流控规则(阈值类型:并发线程数)
以下是一个用睡眠的方式模拟流控规则(阈值类型:并发线程数)的测试接口。
假设我们已经在Sentinel控制台中创建了一个名为test的流控规则,阈值类型为并发线程数,阈值设置为3。
我们可以创建一个Spring Boot接口来测试这个规则,示例如下:
@GetMapping("/test")
@SentinelResource(value = "test", blockHandler = "handleBlock")
public String test() throws InterruptedException {
// 模拟请求处理时间
Thread.sleep(4000);
return "Hello Sentinel!";
}
// 定义 blockHandler 处理请求被限流的情况
public String handleBlock(BlockException ex) {
// 返回请求被限流的提示信息
return "Oops, request is blocked!";
}
以上代码中,我们在原来的示例代码的基础上加入了一个4秒钟的睡眠时间来模拟请求处理的耗时。
然后我们可以postman中在4个窗口中同时打开该接口,来模拟并发请求的场景。当并发线程数达到我们在Sentinel控制台中设置的阈值3时,Sentinel会拦截请求并调用handleBlock方法。我们可以观察是否会出现请求被限流的情况,以及返回结果是否符合预期。
三,高级选项
在Sentinel的流控规则中,流控模式和流控效果是两个重要的概念。
- 流控模式指的是限流的方式,Sentinel提供了三种限流模式:直接、关联、链路。
直接模式是针对单个资源进行限流,可以通过设置单个资源的阈值来限制该资源的访问速率,例如一个接口每秒最多只能接受20个请求,即设置其QPS为20。这种模式适用于针对单个资源进行限制的场景。
关联模式是基于后端关联资源进行限流,例如对于购买商品这个请求,可能需要先检查该商品的库存和用户的余额等后端资源状态,因此可以将每个后端资源状态都视为关联资源进行限流。在关联模式下,当与该资源相关的资源的阈值超过限制时,该资源被限流。关联模式适用于有多个后端关联资源的场景。
链路模式是基于调用链路进行限流,它可以针对某个请求调用链路上的各个节点进行限流。例如一个请求会依次调用订单系统、库存系统和支付系统,在链路模式下可以针对订单系统、库存系统和支付系统的请求均做限流处理。链路模式适用于有多个中间节点的场景,通过限制整个调用链路的请求量来保护系统不会被过度消耗。
流控效果指的是当请求被限流时,Sentinel对请求的处理方式。Sentinel提供了三种处理方式,分别为快速失败、Warm Up、排队等待。
快速失败是一种最常用的限流处理方式。当请求超过阈值时,快速失败会直接拒绝请求并返回错误信息,告知客户端当前服务繁忙。这种方式比较直接,可以迅速避免系统过度消耗。
Warm Up是一种预热方式,可以在系统启动或者在增加节点数量时,通过预热来逐步增加系统的吞吐量,避免系统瞬间压力过大。在Warm Up模式下,当请求超过阈值时,Sentinel会将请求逐步释放出来,逐步增加系统的吞吐量,直到达到最大限制。
排队等待是一种流量控制的方式,其处理方式是将请求放入队列中,等待处理。当请求超过阈值时,Sentinel会将请求放入队列中,等待系统处理能力的释放。这种方式可以保证资源的有效利用,避免资源的浪费,但会增加系统的延迟时间。
在创建流控规则时,我们可以选择合适的流控模式和流控效果,根据具体的业务需求和系统瓶颈进行设置。例如,在高峰期预防请求压力过大时,我们可以选择直接模式和快速失败效果,快速拒绝请求,避免系统宕机;而在流量突增时,我们可以选择Warm Up效果,平滑增加通过的请求量,避免让系统瞬间无法承受过量的请求。
02,熔断降级
一,概念
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。
二,熔断策略
Sentinel提供了三种熔断策略:
1.异常比率熔断:在一段时间内发生异常比例超过设定阈值,即触发熔断策略,否则回复正常。这种策略适用于异常会导致大量错误的场景,可以有效避免被大量异常请求影响系统的稳定性。
2.异常数熔断:在一段时间内异常数超过设定阈值,即触发熔断策略。这种策略适用于单次异常对系统影响很小的场景,可以更精细地保护系统稳定性。
3.慢调用熔断:如果在一段时间内处理请求的时间超过设定的时间,则认为该请求为慢调用,即触发熔断策略。这种策略适用于对响应时间有严格要求的场景,可以有效避免慢调用对系统响应时间超过预设范围的影响。
根据实际业务情况,我们可以选择合适的熔断策略,来达到最优化的保护效果。
三,代码示例
01 慢调用熔断
好的,以下是一个使用Sentinel慢调用熔断策略的测试接口的示例代码:
@RestController
@RequestMapping("/slow")
public class SlowController {
@GetMapping("/method")
@SentinelResource(value = "slowMethod", blockHandler = "handleBlock",
fallback = "handleFallback",
blockHandlerClass = SlowControllerBlockHandler.class,
fallbackClass = SlowControllerFallback.class)
public String slowMethod() throws InterruptedException {
// 模拟一个响应时间为2秒的慢调用
Thread.sleep(2000);
return "Hello, slow method!";
}
}
在上面的示例代码中,我们使用了@GetMapping注解来定义一个GET请求的映射路径,即"/slow/method"的请求路径。在slowMethod这个方法上面,我们使用了@SentinelResource注解,将slowMethod方法包装成Sentinel的资源,并且指定了慢调用熔断的策略。
如果slowMethod方法在一段时间内处理的时间超过设定的时间,则触发熔断策略。在这里,我们定义了blockHandler和fallback这两个参数,它们是用来处理异常情况下的返回信息的。其中blockHandler参数指定了熔断策略的处理方法,即SlowControllerBlockHandler类中的handleBlock方法;fallback参数指定了降级策略的处理方法,即SlowControllerFallback类中的handleFallback方法。在我们的示例代码中,我们将blockHandler和fallback的具体实现留到了SlowControllerBlockHandler和SlowControllerFallback中进行。
下面是SlowControllerBlockHandler和SlowControllerFallback的实现示例代码:
public class SlowControllerBlockHandler {
public static String handleBlock(BlockException ex) {
// 当触发熔断时,返回一个友好的提示信息
return "请求被限流了:" + ex.getRule().toString();
}
}
public class SlowControllerFallback {
public static String handleFallback(Throwable ex) {
return "请求失败,原因是:" + ex.getMessage();
}
}
在SlowControllerBlockHandler中,我们定义了一个handleBlock方法来处理触发熔断时的返回信息;在SlowControllerFallback中,我们定义了一个handleFallback方法来处理请求失败时的返回信息。
实现这些之后,我们就可以使用浏览器或者Postman等工具发送GET请求来访问slowMethod接口,测试慢调用熔断策略的情况了。
02 异常数熔断
下面是一个使用Sentinel异常数熔断策略的测试接口的示例代码:
@RestController
@RequestMapping("/exception")
public class ExceptionController {
private static AtomicInteger count = new AtomicInteger(0);
@GetMapping("/method")
@SentinelResource(value = "exceptionMethod", blockHandler = "handleBlock",
fallback = "handleFallback",
blockHandlerClass = ExceptionControllerBlockHandler.class,
fallbackClass = ExceptionControllerFallback.class)
public String exceptionMethod() {
// 模拟一个产生异常的场景,调用次数达到阈值时触发熔断
if (count.incrementAndGet() % 2 == 0) {
throw new RuntimeException("异常发生了!");
}
return "Hello, exception method!";
}
}
在上面的示例代码中,我们同样将异常策略包装成Sentinel的资源,将exceptionMethod方法用@SentinelResource注解修饰。在exceptionMethod方法中,我们使用了一个AtomicInteger类型的计数器count,每当调用一次exceptionMethod方法时,计数器就会自增1。当计数器的值是2的倍数时,我们就人为制造一个异常并抛出,触发异常熔断。在实际业务场景中,这里的异常可以根据具体的业务情况进行调整。
我们同样设置了blockHandler和fallback这两个参数,用来处理触发熔断时和请求失败时的情况。在这里我们将它们分别放到了ExceptionControllerBlockHandler和ExceptionControllerFallback类中进行处理。
下面是ExceptionControllerBlockHandler和ExceptionControllerFallback的实现示例代码:
public class ExceptionControllerBlockHandler {
public static String handleBlock(BlockException ex) {
// 当触发熔断时,返回一个友好的提示信息
return "请求被限流了:" + ex.getRule().toString();
}
}
public class ExceptionControllerFallback {
public static String handleFallback(Throwable ex) {
return "请求失败,原因是:" + ex.getMessage();
}
}
在ExceptionControllerBlockHandler中,我们定义了handleBlock方法来处理触发熔断时的返回信息;在ExceptionControllerFallback中,我们定义了handleFallback方法来处理请求失败时的返回信息。
实现这些之后,我们可以使用浏览器或者Postman等工具发送GET请求来访问exceptionMethod接口,测试异常数熔断策略的情况了。
03 异常比率熔断
好的,下面是一个使用Sentinel异常比率熔断策略的测试接口的示例代码:
@RestController
@RequestMapping("/ratio")
public class RatioController {
private static AtomicInteger count = new AtomicInteger(0);
@GetMapping("/method")
@SentinelResource(value = "ratioMethod", blockHandler = "handleBlock",
fallback = "handleFallback",
blockHandlerClass = RatioControllerBlockHandler.class,
fallbackClass = RatioControllerFallback.class)
public String ratioMethod() {
// 模拟一个随机产生异常的场景,当异常比率大于阈值时触发熔断
if (count.incrementAndGet() % 3 == 0) {
throw new RuntimeException("异常发生了!");
}
return "Hello, ratio method!";
}
}
在上面的示例代码中,我们同样将异常比率策略包装成Sentinel的资源,将ratioMethod方法用@SentinelResource注解修饰。在ratioMethod方法中,我们同样使用了一个AtomicInteger类型的计数器count,每当调用一次ratioMethod方法时,计数器就会自增1。当计数器的值是3的倍数时,我们就人为制造一个异常并抛出。在实际业务场景中,这里的异常可以根据具体的需求进行调整。
我们同样设置了blockHandler和fallback这两个参数,用来处理触发熔断时和请求失败时的情况。在这里我们将它们分别放到了RatioControllerBlockHandler和RatioControllerFallback类中进行处理。
下面是RatioControllerBlockHandler和RatioControllerFallback的实现示例代码:
public class RatioControllerBlockHandler {
public static String handleBlock(BlockException ex) {
// 当触发熔断时,返回一个友好的提示信息
return "请求被限流了:" + ex.getRule().toString();
}
}
public class RatioControllerFallback {
public static String handleFallback(Throwable ex) {
return "请求失败,原因是:" + ex.getMessage();
}
}
在RatioControllerBlockHandler中,我们定义了handleBlock方法来处理触发熔断时的返回信息;在RatioControllerFallback中,我们定义了handleFallback方法来处理请求失败时的返回信息。
实现这些之后,我们可以使用浏览器或者Postman等工具发送GET请求来访问ratioMethod接口,测试异常比率熔断策略的情况了。
02,热点规则
Sentinel热点规则是一种限流措施,它可以根据某个资源在一定时间段内的流量、QPS、并发数等指标超过预设阈值时,自动触发限流。这种规则可以防止某个资源被不合理地过度使用,保护系统的稳定性和可靠性。
热点规则特别适用于一些高吞吐量的接口或资源,如商品ID、手机号码、IP地址等,这些资源很容易成为系统的瓶颈和热点。例如,当某个商品热度突然上升,会导致该商品ID的请求量急剧增加,这时就需要通过热点规则来限制并发数,防止流量过载,保护系统。
在Sentinel中,你可以通过配置热点规则来限制某个资源的流量,从而保证系统的稳定性。
一,热点规则
首先,我们需要在pom.xml文件中添加Sentinel的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
接下来,我们在sentinel控制台中配置一个热点参数,并为该参数添加热点规则,限制该参数的QPS为2。
配置完毕后,我们可以在控制台上看到该规则的详细信息:
Sentinel热点参数规则中,含有以下三个关键参数:
-
参数索引:指定被限制的参数在方法参数列表中的位置,从0开始,默认值为0。例如,对于方法
public void foo(String arg1, int arg2)
,如果要对参数arg1做限流,则参数索引为0,如果要对参数arg2做限流,则参数索引为1。 -
单机阈值:指定该参数在统计窗口时长内的请求量上限,超过该阈值后,将会触发限流。例如,设置单机阈值为10,则在1秒内,一个应用实例对这个参数的请求量不能超过10次。
-
统计窗口时长:指定限流统计的时间窗口长度,单位为秒。例如,设置窗口时长为5,则限流统计就是每5秒一轮,每轮统计对应窗口时间内的请求量。
通过在Sentinel控制台中设置这三个参数,就可以针对某个参数设置热点参数规则,从而限制该参数的请求量,保护系统的稳定性。
这个热点规则的含义是:在统计窗口时长为5秒的时间内,如果某个参数在同一台机器上的请求量达到1次以上,则将触发限流。
这个参数的位置在方法参数列表中的索引为0。也就是说,统计窗口时长内,对于同一个机器的相同请求参数,请求次数达到1次就会触发限流。
最后,我们在Controller层编写一个接口,并在该接口中使用该热点参数,测试该热点规则是否生效。
@RestController
public class DemoController {
@GetMapping("/test")
@SentinelResource(value = "test", blockHandlerClass = DemoControllerBlockHandler.class, blockHandler = "handleBlock")
public String test(@RequestParam("param") String param) {
return "hello " + param;
}
}
public class DemoControllerBlockHandler {
public static String handleBlock(String param, BlockException e) {
return "限流了...";
}
}
在上面的代码中,我们使用了 @SentinelResource 注解标记了接口,并指定了 blockHandlerClass 和 blockHandler 两个属性,这两个属性指定了接口流量超过限制时的处理方式。
接下来,我们可以使用Postman等工具,连续发送大量的请求,测试该热点规则的生效情况。可以发现,当请求的参数值为热点参数时,接口会被限流。
5秒的时间内,如果某个参数在同一台机器上的请求量达到1次以上,则将触发限流5秒。
总结起来,使用Sentinel热点规则可以轻松地限制某个接口的请求量,保护系统的稳定性。在Spring Boot应用中使用Sentinel也非常简单,只需要添加maven依赖、开启Sentinel支持,并在控制台上配置好规则即可。
二,高级选项
举个例子,某个应用的某个方法入参为一个String,假如我们需要对这个参数进行限流控制,给定热点规则如下:
- 统计窗口时长 10
- 参数类型:String
- 参数值:bilal
- 限流阈值:2
则表示在10s内,如果同一台机器上的第0个请求的该参数的值为 bilal时,请求达到2次时,对该参数的请求进行限流。
最后,我们在Controller层编写一个接口,并在该接口中使用该热点参数,测试该热点规则是否生效。
@RestController
public class DemoController {
@GetMapping("/test")
@SentinelResource(value = "test", blockHandlerClass = DemoControllerBlockHandler.class, blockHandler = "handleBlock")
public String test(@RequestParam("param") String param) {
return "hello " + param;
}
}
public class DemoControllerBlockHandler {
public static String handleBlock(String param, BlockException e) {
return "限流了...";
}
}
在上面的代码中,我们使用了 @SentinelResource 注解标记了接口,并指定了 blockHandlerClass 和 blockHandler 两个属性,这两个属性指定了接口流量超过限制时的处理方式。
接下来,我们可以使用Postman等工具,连续发送大量的请求,测试该热点规则的生效情况。可以发现,当请求的参数值为热点参数时,接口会被限流。
03,授权规则
Sentinel 中的授权规则指的是限制特定资源只允许某些关联应用或 IP 访问的规则。
授权规则可以用于保护资源不被恶意或未授权的访问所滥用。通常情况下,需要对接入到 Sentinel 的所有应用或用户进行授权才能访问被保护的资源。
Sentinel 的授权规则可以基于应用、IP 或者来源分类进行授权。其中,应用和来源分类都是 Sentinel 的概念,具体定义如下:
- 应用:指的是接入 Sentinel 的应用,一个应用可以包含多个资源。
- 来源分类:是 Sentinel 定义的一个概念,表示从哪个网络流量分类来的请求,例如:浏览器、POSTMAN 调用、SDK 调用等。
除了基于应用和来源分类进行授权以外,也可以通过 IP 控制规则和用户控制规则来实现授权。其中:
- IP 控制规则:对特定 IP 进行授权或限制。
- 用户控制规则:对特定的用户进行授权或限制。
需要注意的是,为了保证 Sentinel 的效果,在设置授权规则时应该尽量减少授权粒度尽量细,以防止误操作和意外泄露授权信息。
在 Sentinel 中授权规则的配置中,有三个重要的字段需要了解:资源名、流控应用和授权类型。
- 资源名:表示需要进行限流或者授权保护的资源,例如一个接口 URL、一个方法调用等等。一个资源可以对应多个流控规则和授权规则。
- 流控应用:表示被允许访问资源的应用,也称为黑白名单中的白名单。只有流控应用被授权才能访问对应的资源,否则会被限制或者直接拒绝。如果流控应用未设置,则说明所有应用都允许访问资源。
- 授权类型:表示授权规则的类型,一般包括黑白名单、限流和熔断等类型。其中,黑白名单类型指的是只允许或者拒绝特定应用或者 IP 访问资源;限流类型指的是限制特定应用或者 IP 对资源的访问次数;熔断类型指的是当某个资源出现错误或者异常时,自动停止对该资源的访问请求。
需要注意的是,流控应用是限制或者允许访问资源的关键因素,而授权类型和资源名则决定流控应用访问资源的方式和策略。同时,流控应用也是动态变化的,因此在实际应用中需要注意流控应用的管理和完整性,以保证 Sentinel 规则的正确性和有效性。