Sentinel持久化:
(1)原始模式:
这是Sentinel默认模式,该模式规则下不持久化,重启微服务之后配置的限流降级等规则全部失效。
(2)Pull模式:(拉模式)
如官方文档的上图所示,Sentinel Dashboard推送规给微服务,微服务将规则更新到内存,同时将规则更新到本地文件,以此来实现规则的持久化。
配置依赖:
<!--sentinel-datasource-extension数据源扩展-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
</dependency>
**
* Pull模式规则持久化,持久化到本地生成文件
*/
public class FileDataSourceInit implements InitFunc {
@Override
public void init() throws Exception {
//可以根据需要指定规则文件的位置
String ruleDir = System.getProperty("user.home") + "/sentinel/rules";
//流控
String flowRulePath = ruleDir + "/flow-rule.json";
//降级
String degradeRulePath = ruleDir + "/degrade-rule.json";
//热点
String paramFlowRulePath = ruleDir + "/param-flow-rule.json";
//系统
String systemRulePath = ruleDir + "/system-rule.json";
//授权
String authorityRulePath = ruleDir + "/authority-rule.json";
this.mkdirIfNotExits(ruleDir);
this.createFileIfNotExits(flowRulePath);
this.createFileIfNotExits(degradeRulePath);
this.createFileIfNotExits(paramFlowRulePath);
this.createFileIfNotExits(systemRulePath);
this.createFileIfNotExits(authorityRulePath);
// 流控规则:可读数据源
ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
flowRulePath,
flowRuleListParser
);
// 将可读数据源注册至FlowRuleManager
// 这样当规则文件发生变化时,就会更新规则到内存
FlowRuleManager.register2Property(flowRuleRDS.getProperty());
// 流控规则:可写数据源
WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
flowRulePath,
this::encodeJson
);
// 将可写数据源注册至transport模块的WritableDataSourceRegistry中
// 这样收到控制台推送的规则时,Sentinel会先更新到内存,然后将规则写入到文件中
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<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(
paramFlowRulePath,
paramFlowRuleListParser
);
ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
// 热点参数规则:可写数据源
WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
paramFlowRulePath,
this::encodeJson
);
ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
// 系统规则:可读数据源
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);
}
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);
}
}
在META-INF/service/com.alibaba.csp.sentinel.init.InitFunc里面配置下写入文件规则的全类名:
在Sentinel Dashboard控制台配置规则就写入如下文件
Pull模式实现方法好处是简单,不引入新的依赖,坏处是无法保证监控数据的一致性。
(3)Push模式(推模式):
远程配置中心个人使用的是Nacos:这种方式是将规则存储在nacos配置中心,微服务从nacos配置中心获取规则,这种方式有更好的实时性和一致性保证,生产环境建议使用该方式(支持Nacos、ZooKeeper、Apollo等)
Push模式(推模式)规则持久化到Nacos:
1、添加sentinel-datasource-nacos依赖;
<!--sentinel数据持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2、application.properties配置持久化数据源;
#application.properties配置持久化数据源;配合nacos一起使用
#注册到Nacos集群环境
spring.cloud.sentinel.datasource.ds1.nacos.serverAddr=47.110.237.194:80
spring.cloud.sentinel.datasource.ds1.nacos.dataId=${spring.application.name}.json
#默认分组
spring.cloud.sentinel.datasource.ds1.nacos.groupId=DEFAULT_GROUP
#JSON格式
spring.cloud.sentinel.datasource.ds1.nacos.dataType=json
#流控规则
spring.cloud.sentinel.datasource.ds1.nacos.ruleType=flow
改变Nacos里面的Sentinel规则可以同步到Sentinel Dashboard控制台,但是修改Sentinel控制台的规则不能同步到Nacos的持久化规则里面
Spring Cloud Alibaba Sentinel Dashboard通信原理:
微服务暴露给Sentinel Dashboard的API接口列表:http://localhost:8719/api
Sentinel Dashboard控制台配置修改:
#懒加载、饥饿加载:true表示饥饿加载
#开启饥饿加载 就是一开始启动的时候一次性创建完,而不是设置为false的时候懒加载谁调用用到的时候才加载
spring.cloud.sentinel.eager=true
Spring Cloud Alibaba Sentinel三种保护应用方式:
1、直接用配置拦截所有controller的请求路径(对controller请求埋点):
Sentinel为Spring Boot程序提供了一个starter依赖,由于Sentinel starter默认情况下会给所有的HTTP服务提供限流埋点,所以Spring Boot项目中所有的controller都可以收到sentinel的保护,项目当中引入做下依赖:
<!--spring-cloud-starter-alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
还需要为sentinel配置保护规则,底层是用过一个拦截器
com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor对请求拦截实现。
配置文件:
#关闭sentinel对controller的url的保护(默认为true)
spring.cloud.sentinel.filter.enabled=false
2、通过自定义代码实现埋点:
/**
*
* @return
*/
@GetMapping("/test/{app}")
public String test3(@PathVariable(name = "app") String app){
System.out.println("/test3/{app} --> " + app);
ContextUtil.enter("test3");
Entry entry = null;
try {
entry = SphU.entry("test3");
//受sentinel保护的代码 start
//int a = 10 / 0;
return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
//受sentinel保护的代码 end
}catch (BlockException e){
e.printStackTrace();
//手动写上服务降级的代码
if (e instanceof FlowException) {
return "接口限流了。。。。。。";
} else if (e instanceof DegradeException) {
return "服务降级了。。。。。。";
} else if (e instanceof ParamFlowException) {
return "热点参数限流了。。。。。。";
} else if (e instanceof SystemBlockException) {
return "触发系统保护规则。。。。。。";
} else if (e instanceof AuthorityException) {
return "授权规则不通过。。。。。。";
}
return "熔断了。。。。。。";
}catch (ArithmeticException e){
//对 int a = 10 / 0; 异常的监控
Tracer.trace(e);
return "除数不能为0";
}finally {
if (entry != null){
entry.exit();
}
ContextUtil.exit();
}
}
采用注解@SentinelResource(value = “app”)实现埋点:
/**
* blockHandler = "block", blockHandlerClass = MyBlockHandlerClass.class 处理限流和降级
* fallback = "fallback", fallbackClass = MyFallbackClass.class 处理限流和降级
*
* @param a
* @param b
* @return
*/
@GetMapping("/app") // 埋点:加入sentinel的监控
@SentinelResource(value = "app", fallback = "fallback", fallbackClass = MyFallbackClass.class)
// @SentinelResource(value = "app", blockHandler = "block", blockHandlerClass = MyBlockHandlerClass.class)
public String app(@RequestParam(value = "a", required = false) String a,
@RequestParam(value = "b", required = false) String b) {
System.out.println("/app/--> " + a + "--" + b);
return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
}
下面就介绍下@SentinelResource里面的方法:
属性 | 作用 | 是否必须 |
---|---|---|
value | 资源名称(埋点名称) | 是 |
entryType | entry类型,标记流量的方向,取值IN或者OUT,默认OUT | 否 |
blockHandler | 处理BlockException的函数名称。函数要求:1. 必须是 public2.返回类型与原方法一致3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法 | 否 |
blockHandlerClass | 存放blockHandler的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同blockHandler。 | 否 |
fallback | 用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:1. 返回类型与原方法一致2. 参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法 | 否 |
defaultFallback | 用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求:1. 返回类型与原方法一致2. 方法参数列表为空,或者有一个 Throwable 类型的参数。3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。 | 是 |
fallbackClass | 存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。 | 否 |
exceptionsToIgnore | 指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。 | 是 |
exceptionsToTrace | 需要trace的异常 | Throwable |
Sentinel对RestTemplate模式调用和Feign模式调用流控熔断:
#true开启sentinel对resttemplate的支持,false则关闭
resttemplate.sentinel.enabled=true
/**
* ribbon负载均衡,默认是:ZoneAvoidanceRule
* @return
*/
@SentinelRestTemplate(blockHandler ="blockA" ,blockHandlerClass = MyBlockHandlerClass.class) //服务限流
//@SentinelRestTemplate(fallback = "fallbackA",fallbackClass = MyBlockHandlerClass.class) //服务降级
@LoadBalanced //负载均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
#true开启sentinel对feign的支持,false则关闭
feign.sentinel.enabled=true
@FeignClient(name = "29-nacos-discovery-provider")
fallback = EchoServiceFallback.class,
// fallbackFactory = EchoFeignServiceFallbackFactory.class,
configuration = FeignConfiguration.class)
public interface EchoFeignService {
@GetMapping("/echo/hello")
default String hello() {
return "hello";
}
@GetMapping("/echo/{str}")
String echo(@PathVariable("str") String str);
@GetMapping("/divide")
String divide(@RequestParam("a") Integer a, @RequestParam("b") Integer b);
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/77245.html