1 @SentinelResource的使用
在定义了资源点之后,我们可以通过Dashboard来设置限流和降级策略来对资源点进行保护。同时还能
通过@SentinelResource来指定出现异常时的处理策略。
@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。其主要参数如下:
定义限流和降级后的处理方法
- 方式一:直接将限流和降级方法定义在方法中
@Service
@Slf4j
public class OrderServiceImpl3 {int i = 0;@SentinelResource(value = "message",blockHandler = "blockHandler",//指定发生BlockException时进入的方法fallback = "fallback"//指定发生Throwable时进入的方法)public String message() {i++;if (i % 3 == 0) {throw new RuntimeException();}return "message";}//BlockException时进入的方法public String blockHandler(BlockException ex) {log.error("{}", ex);return "接口被限流或者降级了...";}//Throwable时进入的方法public String fallback(Throwable throwable) {log.error("{}", throwable);return "接口发生异常了...";}
}
- 方式二: 将限流和降级方法外置到单独的类中
@Service
@Slf4j
public class OrderServiceImpl3 {int i = 0;@SentinelResource(value = "message",blockHandlerClass = OrderServiceImpl3BlockHandlerClass.class,blockHandler = "blockHandler",fallbackClass = OrderServiceImpl3FallbackClass.class,fallback = "fallback")public String message() {i++;if (i % 3 == 0) {throw new RuntimeException();}return "message4";}
}
@Slf4j
public class OrderServiceImpl3BlockHandlerClass {//注意这里必须使用static修饰方法public static String blockHandler(BlockException ex) {log.error("{}", ex);return "接口被限流或者降级了...";}
}
@Slf4j
public class OrderServiceImpl3FallbackClass {
//注意这里必须使用static修饰方法public static String fallback(Throwable throwable) {log.error("{}", throwable);return "接口发生异常了...";}
}
2 Sentinel规则持久化
通过前面的讲解,我们已经知道,可以通过Dashboard来为每个Sentinel客户端设置各种各样的规
则,但是这里有一个问题,就是这些规则默认是存放在内存中,极不稳定,所以需要将其持久化。
本地文件数据源会定时轮询文件的变更,读取规则。这样我们既可以在应用本地直接修改文件来更
新规则,也可以通过 Sentinel 控制台推送规则。以本地文件数据源为例,推送过程如下图所示:
首先 Sentinel 控制台通过 API 将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。
1 编写处理类
package com.itheima.config;
//规则持久化
public class FilePersistence implements InitFunc {@Value("spring.application:name")private String appcationName;@Overridepublic void init() throws Exception {String ruleDir = System.getProperty("user.home") + "/sentinel-
rules/"+appcationName;String flowRulePath = ruleDir + "/flow-rule.json";String degradeRulePath = ruleDir + "/degrade-rule.json";String systemRulePath = ruleDir + "/system-rule.json";String authorityRulePath = ruleDir + "/authority-rule.json";String paramFlowRulePath = ruleDir + "/param-flow-rule.json";this.mkdirIfNotExits(ruleDir);this.createFileIfNotExits(flowRulePath);this.createFileIfNotExits(degradeRulePath);this.createFileIfNotExits(systemRulePath);this.createFileIfNotExits(authorityRulePath);this.createFileIfNotExits(paramFlowRulePath);// 流控规则ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new
FileRefreshableDataSource<>(flowRulePath,flowRuleListParser);FlowRuleManager.register2Property(flowRuleRDS.getProperty());WritableDataSource<List<FlowRule>> flowRuleWDS = new
FileWritableDataSource<>(flowRulePath,this::encodeJson);WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);// 降级规则ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new
FileRefreshableDataSource<>(degradeRulePath,degradeRuleListParser);DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());WritableDataSource<List<DegradeRule>> degradeRuleWDS = new
FileWritableDataSource<>(degradeRulePath,this::encodeJson);WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);// 系统规则ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new
FileRefreshableDataSource<>(systemRulePath,systemRuleListParser);SystemRuleManager.register2Property(systemRuleRDS.getProperty());WritableDataSource<List<SystemRule>> systemRuleWDS = new
FileWritableDataSource<>(systemRulePath,this::encodeJson);WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);// 授权规则ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new
FileRefreshableDataSource<>(authorityRulePath,authorityRuleListParser);AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new
FileWritableDataSource<>(authorityRulePath,this::encodeJson);WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);// 热点参数规则ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new
FileRefreshableDataSource<>(paramFlowRulePath,paramFlowRuleListParser);ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new
FileWritableDataSource<>(paramFlowRulePath,this::encodeJson);ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);}private Converter<String, List<FlowRule>> flowRuleListParser = source ->
JSON.parseObject(source,new TypeReference<List<FlowRule>>() {});private Converter<String, List<DegradeRule>> degradeRuleListParser = source
-> JSON.parseObject(source,new TypeReference<List<DegradeRule>>() {});private Converter<String, List<SystemRule>> systemRuleListParser = source ->
JSON.parseObject(source,new TypeReference<List<SystemRule>>() {});private Converter<String, List<AuthorityRule>> authorityRuleListParser =
source -> JSON.parseObject(source,new TypeReference<List<AuthorityRule>>() {});private Converter<String, List<ParamFlowRule>> paramFlowRuleListParser =
source -> JSON.parseObject(source,new TypeReference<List<ParamFlowRule>>() {});private void mkdirIfNotExits(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {file.mkdirs();}}private void createFileIfNotExits(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {file.createNewFile();}}private <T> String encodeJson(T t) {return JSON.toJSONString(t);}
}
2 添加配置
在resources下创建配置目录 META-INF/services ,然后添加文件
com.alibaba.csp.sentinel.init.InitFunc
在文件中添加配置类的全路径
com.itheima.config.FilePersistence