Sentinel:2.Sentinel的基本使用(二)降级规则、热点规则
文章目录
- 1.在项目中使用Sentinel:降级规则
- 1.1 在HelloServiceImpl中新增接口testDegradeRule(),添加注解@SentinelResource
- 1.2 新建目录fallbackhandler,并创建熔断降级类FallbackHandler
- 1.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
- 1.4 为接口testDegradeRule()添加一条降级规则
- 2.在项目中使用Sentinel:热点规则
- 2.1 在HelloServiceImpl中新增接口getJson()和getHtml(),添加注解@SentinelResource
- 2.2 新建NacosSamplepProviderConstants.java,作为请求资源
- 2.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
- 2.4 测试热点规则(基础设置):为接口getJson()添加一条热点规则
- 2.5 测试热点规则(高级设置):为接口getHtml()添加一条热点规则
- 3.小练习
- 本文示例源码:
继续沿用上一篇中的项目:module:nacos-sample-provider,以它为例来演示Sentinel的降级规则和热点规则的使用。
1.在项目中使用Sentinel:降级规则
1.1 在HelloServiceImpl中新增接口testDegradeRule(),添加注解@SentinelResource
HelloServiceImpl.java
package org.wy.provider;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.wy.provider.blockhandler.BlockHandler;
import org.wy.provider.fallbackhandler.FallbackHandler;
@RestController
@RefreshScope
public class HelloServiceImpl {
// @Value可以从Nacos配置中心的配置文件中读取对应的配置变量值
// ${}中的key要与配置文件中的key一致,否则无法读取
@Value("${testValue}")
private String testValue;
// 记录访问次数
private static int count = 0;
@GetMapping(value = "/hi")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "sayHello", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForSayHello")
public String sayHello(@RequestParam(name = "name") String name) {
return "Hello World: " + name;
}
// 新增一个接口,用于验证"@Value的功能"
@GetMapping(value = "/testValue")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "getValueFromNacosConfigServer", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForGetValueFromNacosConfigServer")
public String getValueFromNacosConfigServer() {
return "testValue is: " + testValue;
}
// 新增一个接口,用于验证降级规则
@GetMapping(value = "/degrade")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// fallback 是当前资源访问发生降级时的处理接口,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "testDegradeRule", fallbackClass = FallbackHandler.class, fallback = "fallbakcHandlerForTestDegradeRule")
public String testDegradeRule() {
// 保证count为奇数时异常,偶数时不异常
if ((count++ & 1) == 1) {
throw new RuntimeException("人为制造异常");
} else {
return "降级测试:不发生异常";
}
}
}
1.2 新建目录fallbackhandler,并创建熔断降级类FallbackHandler
FallbackHandler.java
package org.wy.provider.fallbackhandler;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import java.util.logging.Logger;
/** * 定义熔断降级的处理类 * 注意,返回类型和参数要与调用者一致,且都需要添加异常类,并且方法的修饰符必须是public static * 并且可以额外选填一个 Throwable 类型的参数用于接收对应的异常 */
public class FallbackHandler {
private static Logger logger = Logger.getLogger(FallbackHandler.class.toString());
/** * 当testDegradeRule接口访问被降级时,就会调用该接口 * 该函数的传参和返回值类型必须与资源点的传参一样,并且可以额外选填一个 Throwable 类型的参数用于接收对应的异常 * * @param throwable * @return */
public static String fallbakcHandlerForTestDegradeRule(Throwable throwable) {
if (throwable instanceof RuntimeException) {
logger.warning("接口[/degrade]访问失败,原因是:" + throwable.getMessage());
return "接口[/degrade]访问失败,原因是:" + throwable.getMessage();
} else if (throwable instanceof DegradeException) {
DegradeException e = (DegradeException) throwable;
DegradeRule rule = e.getRule();
int time = rule.getTimeWindow();
logger.warning("接口[/degrade]访问被降级,预计[" + time + "]秒内无法访问");
return "接口[/degrade]访问被降级,预计[" + time + "]秒内无法访问";
} else {
return "";
}
}
}
1.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
【注意】
启动nacos-sample-provider服务后,需要先访问一下@SentinelResource注册的资源,才能将对应的资源注册到Sentinel,从而对该资源的访问添加各种规则
1.4 为接口testDegradeRule()添加一条降级规则
为了方便演示,设置一条“异常数为5”的降级规则, 然后快速点击刷新,即可触发熔断,如下图:
2.在项目中使用Sentinel:热点规则
2.1 在HelloServiceImpl中新增接口getJson()和getHtml(),添加注解@SentinelResource
HelloServiceImpl.java
package org.wy.provider;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.wy.provider.blockhandler.BlockHandler;
import org.wy.provider.fallbackhandler.FallbackHandler;
@RestController
@RefreshScope
public class HelloServiceImpl {
// @Value可以从Nacos配置中心的配置文件中读取对应的配置变量值
// ${}中的key要与配置文件中的key一致,否则无法读取
@Value("${testValue}")
private String testValue;
// 记录访问次数
private static int count = 0;
@GetMapping(value = "/hi")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "sayHello", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForSayHello")
public String sayHello(@RequestParam(name = "name") String name) {
return "Hello World: " + name;
}
// 新增一个接口,用于验证"@Value的功能"
@GetMapping(value = "/testValue")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// blockHandler 是处理BlockException的接口名称,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "getValueFromNacosConfigServer", blockHandlerClass = BlockHandler.class, blockHandler = "blockHandlerForGetValueFromNacosConfigServer")
public String getValueFromNacosConfigServer() {
return "testValue is: " + testValue;
}
// 新增一个接口,用于验证降级规则
@GetMapping(value = "/degrade")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
// fallback 是当前资源访问发生降级时的处理接口,接口默认需要和原方法在同一个类中
// 如果希望使用其他类的函数,需要指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
@SentinelResource(value = "testDegradeRule", fallbackClass = FallbackHandler.class, fallback = "fallbakcHandlerForTestDegradeRule")
public String testDegradeRule() {
// 保证count为奇数时异常,偶数时不异常
if ((count++ & 1) == 1) {
throw new RuntimeException("人为制造异常");
} else {
return "降级测试:不发生异常";
}
}
// 新增一个接口,用于验证热点规则:基础设置
@GetMapping(value = "/json")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
@SentinelResource(value = "getJson")
// 这里就不要使用@RequestParam了,否则不管是否在url中填写,入参会一直是被访问状态,这样无法测试热点规则
public String getJson(Boolean json1, Boolean json2) {
if (json1 != null && json1) {
return NacosSamplepProviderConstants.json1;
}
if (json2 != null && json2) {
return NacosSamplepProviderConstants.json2;
}
return NacosSamplepProviderConstants.json3;
}
// 新增一个接口,用于验证热点规则:高级设置
@GetMapping(value = "/html/{id}")
// value 是资源名称,要确保与Sentinel服务中设置的一致且唯一,与Spring的AOP中的切点概念很相似
@SentinelResource(value = "getHtml")
// 这里就不要使用@RequestParam了,否则不管是否在url中填写,入参会一直是被访问状态,这样无法测试热点规则
public String getHtml(@PathVariable int id) {
if (id <= 0 || id > 3) {
return NacosSamplepProviderConstants.errorHtml;
}
return NacosSamplepProviderConstants.html[id - 1];
}
}
2.2 新建NacosSamplepProviderConstants.java,作为请求资源
NacosSamplepProviderConstants.java
package org.wy.provider;
public class NacosSamplepProviderConstants {
public static String json1 = "{\"name\":\"god\",\"age\":\"25\"}";
public static String json2 = "{\"name\":\"godness\",\"age\":\"18\"}";
public static String json3 = "{\"name\":\"me\",\"age\":\"3\"}";
public static String[] html = {
"<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第1个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>",
"<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第2个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>",
"<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 第3个 HTML 页面 </p>\n" + "</body>\n" + "\n" + "</html>"
};
public static String errorHtml = "<html>\n" + "\n" + "<head>\n" + "<title>测试热点规则</title>\n" + "</head>\n" + "\n" + "<body>\n" + "<p> 404!!! </p>\n" + "</body>\n" + "\n" + "</html>";
}
2.3 启动nacos-sample-provider,然后在Sentinel-Dashboard控制台中可以看到对应的菜单
【注意】
启动nacos-sample-provider服务后,需要先访问一下@SentinelResource注册的资源,才能将对应的资源注册到Sentinel,从而对该资源的访问添加各种规则
2.4 测试热点规则(基础设置):为接口getJson()添加一条热点规则
- 参数索引:0对应第一个参数,1对应第二个参数,以此类推;
- 参数索引:从0开始,到该值为止的区间内的参数被访问时,会受该条规则限制。
2.5 测试热点规则(高级设置):为接口getHtml()添加一条热点规则
- 高级设置:需要先添加一个基础的热点规则,对资源名下的所有资源有一个统一的限制;
- 高级设置:然后在高级设置中,单独对某个或多个资源再做具体的限制(高级设置中的阈值可以比基础设置中的大)。
3.小练习
读者可以在热点规则(高级设置)中,尝试一下总规则阈值小于特例阈值的效果,如下图:
本文示例源码:
GitHub:WangYe8613/scanacos
降级规则:
[commit id:c058d158bfe212d8ae37411dcc436d66bfb87620]
热点规则:
[commit id:3819be0c09c16c4e1b73f97c3e4dce3b44e19fd9]
还没有评论,来说两句吧...