【Spring Cloud】全面解析服务容错中间件 Sentinel 持久化两种模式

文章目录

  • 推送模式
  • 本地文件持久化(拉模式)
    • 配置yml
    • 编写处理类
    • 添加配置
    • 演示
  • 配置中心持久化(推模式)
    • 修改nacos在sentinel中生效
      • 引入依赖
      • 配置文件
    • 修改sentinel在nacos中生效
      • 下载源码
      • 更改代码
      • 演示
  • 总结

推送模式

Sentinel 规则的推送有下面三种模式:
在这里插入图片描述

通过前面的讲解,我们已经知道,可以通过 Dashboard 来为每个 Sentinel 客户端设置各种各样的规则,这种属于原始模式。这种模式存在一个问题,就是这些规则默认是存放在内存中的,极不稳定,所以需要将其持久化。

在这里插入图片描述

为了达到持久化的目标,我们需要进行改造,改造的方案有两种:本地文件持久化(拉模式)、配置中心持久化(推模式)

本地文件持久化(拉模式)

拉模式又被称为 pull 模式,它的数据源(如本地文件、RDBMS等)一般是可写入的。本地文件数据源会定时轮询文件的变更,读取规则。这样我们既可以在应用本地直接修改文件来更新规则,也可以通过 Sentinel 控制台推送规则。以本地文件数据源为例,推送过程如下图所示:

在这里插入图片描述

首先 Sentinel 控制台通过API将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull模式的数据源时一般不需要对Sentinel控制台进行改造。这种实现方法好处是简单,坏处是无法保证监控数据的一致性。

配置yml

#数据库配置
spring:cloud:sentinel:eager: truetransport:port: 9998 #跟控制台交流的端口,随意指定一个未使用的端口即可dashboard: localhost:8080  #指定控制台服务的地址filter:enabled: false

编写处理类

实现 InitFunc 接口,在 init 中处理 DataSource 初始化逻辑,并利用 SPI 机制实现加载。

public class FilePersistence implements InitFunc {@Value("${spring.application.name}")private String applicationName;@Overridepublic void init() throws Exception {//创建规则文件String ruleDir = System.getProperty("user.home") + "/sentinel-rules/" + applicationName;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,source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>(){}));//将可读数据源注册至 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,source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>(){}));DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(degradeRulePath,this::encodeJson);WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);//系统规则ReadableDataSource<String, List<SystemRule>> systemRuleRDS= new FileRefreshableDataSource<>(systemRulePath,source -> JSON.parseObject(source, new TypeReference<List<SystemRule>>(){}));SystemRuleManager.register2Property(systemRuleRDS.getProperty());WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(systemRulePath,this::encodeJson);WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);//授权规则ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(authorityRulePath,source-> JSON.parseObject(source, new TypeReference<List<AuthorityRule>>(){}));AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(authorityRulePath, this::encodeJson);WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);//热点参数规则ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(paramFlowRulePath,source-> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>(){}));ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(paramFlowRulePath,this::encodeJson);ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);}
}
  • FileRefreshableDataSource:每次更新规则时自动读取持久化文件更新到map缓存。
  • FileWritableDataSource:写数据源,将 sentinel 控制台发送过来的规则信息写到持久化文件中。在客户端的socket接收到规则信息后,更新缓存的时候也会将规则信息写入文件中持久化。

添加配置

在resources下创建配置目录 META-INF/services,然后添加文件com.alibaba.csp.sentinel.init.InitFunc,在文件中添加配置类的全路径it.aq.cheetah.config.FilePersistence

这样当在 Dashboard 中修改了配置后,Dashboard 会调用客户端的接口修改客户端内存中的值,同时将配置写入文件中,这样操作的话规则是实时生效的,如果是直接修改文件中的内容,这样需要等定时任务3秒后执行才能读到最新的规则。接下来我们演示下:

演示

编写测试类

@RestController
@RequestMapping("/product2")
@Slf4j
public class ProductController2 {@RequestMapping("/test")@SentinelResource(value = "test")public String test() {return "product2";}
}

启动项目,发现在目录下生成了空的规则文件

在这里插入图片描述
在页面上增加流控规则

在这里插入图片描述

然后去看文件flow-rule.json,发现存到了本地文件中

在这里插入图片描述
接着我们仿照该规则仿写一个熔断规则,然后查看网页数据确实生效了

在这里插入图片描述

配置中心持久化(推模式)

推模式又叫 Push 模式,它是通过注册中心实现的,Sentinel控制台——>配置中心——>Sentinel数据源——>Sentinel
在这里插入图片描述
用户不仅可以通过sentinel控制台进行更新,也可以通过nacos配置中心进行更新,所以在sentinel控制台或nacos中修改规则后,都需要通知对方刷新最新的配置。

修改nacos在sentinel中生效

引入依赖

我们在之前项目的基础上引入新的依赖

<!--nacos配置中心-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--以nacos作为sentinel数据源的依赖--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>

配置文件

nacos 配置:因为我们用nacos作为了配置中心,我们可以将sentinel的基本配置放入到nacos中就可以了,所以当前服务的yml配置文件中只需要写一些基本的配置就可以了。

spring:cloud:nacos:discovery:server-addr: localhost:8848config:server-addr: localhost:8848file-extension: yml

在nacos中配置sentinel信息

spring: cloud:sentinel:transport:# 跟控制台交流的端口,随意指定一个未使用的端口即可port: 9998 # 指定控制台服务的地址dashboard: localhost:8080  # sentinel用nacos作为数据源的配置datasource: #流控管理(这个名称可以自定义)flow-control: # 告诉sentinel用nacos作为数据源nacos: # 配置中心里执行文件的 dataIddataId: shop-product-flow.json  # nacos的地址serverAddr: 127.0.0.1:8848 # 指定文件配置的是哪种规则rule-type: flow

注意:如果使用的 namespace 不是默认的,记得配置 namespace 参数。

  • dataId:需要告诉 sentinel 读取配置中心中的哪个配置文件;
  • rule-type:告诉 sentinel 配置文件配置的控制规则,flow:流控、degrade:熔断、param-flow 热点参数,想看有哪些规则参数可以查看com.alibaba.cloud.sentinel.datasource包下的枚举类:RuleType。
public enum RuleType {/*** flow.*/FLOW("flow", FlowRule.class),/*** degrade.*/DEGRADE("degrade", DegradeRule.class),/*** param flow.*/PARAM_FLOW("param-flow", ParamFlowRule.class),/*** system.*/SYSTEM("system", SystemRule.class),/*** authority.*/AUTHORITY("authority", AuthorityRule.class),/*** gateway flow.*/GW_FLOW("gw-flow","com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule"),/*** api.*/GW_API_GROUP("gw-api-group","com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition");

shop-product-flow.json文件中配置【流控规则】

[{"clusterConfig": {"acquireRefuseStrategy": 0,"clientOfflineTime": 2000,"fallbackToLocalWhenFail": true,"resourceTimeout": 2000,"resourceTimeoutStrategy": 0,"sampleCount": 10,"strategy": 0,"thresholdType": 0,"windowIntervalMs": 1000},"clusterMode": false,"controlBehavior": 0,"count": 10.0,"grade": 1,"limitApp": "default","maxQueueingTimeMs": 500,"resource": "/product2/test","strategy": 0,"warmUpPeriodSec": 10}
]

在这里插入图片描述

然后去 dashboard 中查看,发现流控规则已经在控制中显示了

在这里插入图片描述
目前我们已经实现了在 nacos 中配置的文件直接在sentinel dashboard中生效,但是我们在sentinel dashboard中修改了配置,nacos 是不会监听到并进行修改的。接下来我们实现一下通过 sentinel 控制台设置的规则直接持久化到 nacos配置中心。

修改sentinel在nacos中生效

Sentinel 控制台提供 DynamicRulePublisherDynamicRuleProvider 接口用于实现应用维度的规则推送和拉取。

下载源码

https://github.com/alibaba/Sentinel/releases下载dashboard的代码源码。

在这里插入图片描述

解压之后打开sentinel-dashboard项目,将 pom.xml 文件中作用域为 test 的注释掉,注释掉后默认的作用域为 compile。

  • test:作用域表示该依赖项只在测试时有用,在编译和运行时不会被用到。
  • compile:作用域范围的依赖项在所有情况下都是有效的,包括编译、运行和测试。

把 test 包下的两个类复制过来

在这里插入图片描述

  • NacosConfigUtil 类主要就是 nacos 配置的规则,比如配置文件的后缀,分组Group_ID等等。因为我用的分组是默认分组,所以改为DEFAULT_GROUP,我之前的规则文件是shop-product-flow.json,所以我把规则文件后缀FLOW_DATA_ID_POSTFIX改为"-flow.json"。
  • NacosConfig类是为了注入nacos的信息以及转换器类。

更改代码

application.properties 中增加 nacos 的配置

# nacos 配置
nacos.serverAddr=localhost:8848
nacos.username=nacos
nacos.password=nacos

NacosConfig 修改为从配置文件中获取nacos配置

 @Beanpublic ConfigService nacosConfigService() throws Exception {Properties properties = new Properties();//Nacos地址properties.put("serverAddr", serverAddr);//Nacos用户名properties.put("username", username);//Nacos密码properties.put("password", password);return ConfigFactory.createConfigService(properties);}

com.alibaba.csp.sentinel.dashboard.rule.FlowRuleApiPublisher#publish方法中增加推送到nacos的逻辑代码

//将规则推送到nacos
configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, converter.convert(rules));

com.alibaba.csp.sentinel.dashboard.rule.FlowRuleApiProvider#getRules方法中修改为从nacos中读取配置的逻辑

@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, 3000);if (StringUtil.isEmpty(rules)) {return new ArrayList<>();}return converter.convert(rules);
}

改造流控的controller类FlowControllerV1,将配置保存到内存中的逻辑改为保存到nacos中

@Autowired
@Qualifier("flowRuleDefaultProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;@Autowired
@Qualifier("flowRuleDefaultPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app,@RequestParam String ip,@RequestParam Integer port) {......try {
//            List<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);//从nacos中读取规则List<FlowRuleEntity> rules = ruleProvider.getRules(app);rules = repository.saveAll(rules);return Result.ofSuccess(rules);} catch (Throwable throwable) {logger.error("Error when querying flow rules", throwable);return Result.ofThrowable(-1, throwable);}
}private void publishRules(String app, String ip, Integer port) throws Exception {//将规则推送到nacosList<FlowRuleEntity> rules = repository.findAllByApp(app);rulePublisher.publish(app, rules);//        List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
//        return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}//其余调用publishRules方法的地方做下简单调整

演示

启动当前项目,流控规则中存在我们之前在nacos中创建的文件,我们将原来的单机阈值从10改为12,然后保存。查看nacos中配置文件的数据,发现已经生效了。

在这里插入图片描述
至于其他规则,大家可以自行实现,此处就不一一实现了

在这里插入图片描述

总结

到这儿,服务容错中间件Sentinel的两种持久化模式就已经介绍完了。下一篇将为大家带来Feign整合容错组件 Sentinel 的文章,敬请期待吧!

后续的文章,我们将继续完善我们的微服务系统,集成更多的Alibaba组件。想要了解更多JAVA后端知识,请点击文末名片与我交流吧。留下您的一键三连,让我们在这个寒冷的东西互相温暖吧!

参考链接:

  • https://blog.csdn.net/weixin_36279234/article/details/130922604;
  • https://blog.csdn.net/u022812849/article/details/131206976;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/14631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

allegro 无法删除Xnet

allegro 无法删除Xnet Orcad中打开Constraint Manager之后&#xff0c;再生成网表&#xff0c;导入PCB后就会出现一堆Xnet网络。无法去除Xnet。 解决办法 在原理图ORCAD中&#xff0c; 1、打开Edit Object properties 2、选择Filter by:Capture 3、点击New Property 4、设置…

火山引擎边缘云亮相 Force 原动力大会,探索 AI 应用新范式

5月15日&#xff0c;2024 春季火山引擎 FORCE 原动力大会在北京正式举办。大会聚焦 AI 主题&#xff0c;以大模型应用为核心、以 AI 落地为导向&#xff0c;展示了火山引擎在大模型、云计算领域的实践应用&#xff0c;携手汽车、手机终端、金融、消费、互联网等领域的专家和企业…

2024042102-array-list

数组 Array 一、前言 数组是数据结构还是数据类型&#xff1f; 数组只是个名称&#xff0c;它可以描述一组操作&#xff0c;也可以命名这组操作。数组的数据操作&#xff0c;是通过 idx->val 的方式来处理。它不是具体要求内存上要存储着连续的数据才叫数据&#xff0c;而…

js积累三(web页面一段时间未操作,退出登录)

//核心代码&#xff0c;已封装function CountDownLogout() {/* if 30 seconds no operation then logout */var maxTime 30; // seconds&#xff0c;可自行修改时长var time_time maxTime;/* 鼠标点击事件 */$(document).mousedown(function(){time_time maxTime; //…

EI会议的最佳论文奖是什么?如何申请?

EI会议的最佳论文奖通常是指在EI&#xff08;工程索引&#xff0c;Engineering Index&#xff09;收录的学术会议中&#xff0c;评选出的表现最优秀的论文奖项。以下是关于该奖项的一些基本信息及申请步骤&#xff1a; 最佳论文奖的含义 评选标准&#xff1a;最佳论文奖通常基…

多线程、进程、线程五种状态、synchronized、volatile、Lock、CAS、死锁、ThreadLocal

1、并发编程 并发编程三要素 原子性&#xff1a;只一个操作要么全部成功&#xff0c;要么全部失败可见性&#xff1a;一个线程对共享变量的修改&#xff0c;其他线程能够立刻看到有序性&#xff1a;程序执行的顺序按照代码的先后顺序执行 synchronized&#xff0c;Lock解决原…

前端vue 动态加载ts文件,动态调用ts内的方法

业务场景: 在某个业务场景中, 我们需要在数据库配置ts文件路径,和需要调用的函数名称, 前端需要再指定的场景下,触发对应的函数, 并执行处理逻辑,返回结果. 实现: 这是一个数据库配置生成的动态表单 动态校验的例子, 需要引用动态的函数校验 任意一个js文件, common1.ts c…

大模型日报|今日必读的 13 篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.MIT新研究&#xff1a;并非所有语言模型特征都是线性的 最近的研究提出了线性表征假说&#xff1a;语言模型通过操作激活空间中概念&#xff08;“特征”&#xff09;的一维表征来执行计算。与此相反&#xff0c;来…

CHI dataless 传输——CHI(4)

上篇介绍了read的操作类型&#xff0c;本篇我们来介绍一下dataless 目录 一、dataless操作概览 二、Non-CMO (Non-Cache Maintenance Operation) 1、CleanUnique 2、StashOnce and StashOnceSep 3、Evict 三、CMO (Cache Maintenance Operation) 一、dataless操作概览 名…

忍の摸头之术游戏娱乐源码

本资源提供给大家学习及参考研究借鉴美工之用&#xff0c;请勿用于商业和非法用途&#xff0c;无任何技术支持&#xff01; 忍の摸头之术游戏娱乐源码&#xff0c;抖音上面非常火的摸头杀画面,看得我眼花缭乱,源码拿去玩吧&#xff1b; 目录说明 忍の摸头之术&#xff1a;域…

轻松同步:将照片从三星手机传输到iPad的简便方法

概括 想要在新 iPad 上查看三星照片吗&#xff1f;但是&#xff0c;如果您不知道如何将照片从三星手机传输到 iPad&#xff0c;则无法在 iPad 上查看图片。为此&#xff0c;本文分享了 7 个有用的方法&#xff0c;以便您可以使用它们在不同操作系统之间轻松发送照片。现在&…

EfficientSAM分割对象后求其中图像中的高

1 分割对象 EfficientSAM https://github.com/yformer/EfficientSAM 2 计算在图像中最高点即y值最小点 import os import cv2def read_images(folder_path):image_files [f for f in os.listdir(folder_path) iff.endswith(".jpg") or f.endswith(".png&quo…

虚拟化技术[1]之服务器虚拟化

文章目录 虚拟化技术简介数据中心虚拟化 服务器虚拟化服务器虚拟化层次寄居虚拟化裸机虚拟化VMM无法直接捕获特权指令解决方案 服务器虚拟化底层实现CPU虚拟化内存虚拟化I/O设备虚拟化 虚拟机迁移虚拟机动态迁移迁移内容&#xff1a;内存迁移迁移内容&#xff1a;网络资源迁移迁…

小短片创作-组装场景(一)

1、项目基础设置 通过第三人称模板&#xff0c;创建1个项目 1.自动曝光&#xff1a;关闭&#xff0c;因为要做专业的小短片&#xff0c;曝光需要手动控制。 2.扩展自动曝光中的默认亮度范围&#xff1a;启用 3.全局光照系统&#xff1a;选择屏幕空间光照&#xff08;SSGI&am…

Transformer详解常见面试问题

文章目录 1. 各模块解决1.1 输入部分1.2 多头注意力&#xff08;作者使用8个头&#xff09;1.3 残差和LayerNorm1.4 Decoder部分 2.Transformer经典问题2.1 tranformer为何使用多头注意力机制&#xff1f;2.2 Transformer相比CNN的优缺点2.3 Encoder和decoder的区别&#xff1f…

Spring中RestTemplate用法

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 RestTemplate 是从…

自编译frida得一些记录

frida编译 这个过程坑肯定很多 但是只要大方向对得&#xff0c;解决掉每个小错误达到目的就ok得 # 就是想自己把frida代码done下来改一改 然后看看git clone gitgithub.com:frida/frida.git git fetch git checkout 14.1.3# 下载node包管理工具 apt install nvm nvm install …

Web Speech API(1)—— SpeechRecognition

Web Speech API 使你能够将语音数据合并到 Web 应用程序中。Web Speech API 有两个部分&#xff1a;SpeechSynthesis 语音合成&#xff08;文本到语音 TTS&#xff09;和 SpeechRecognition 语音识别&#xff08;异步语音识别&#xff09;。 SpeechRecognition 语音识别通过 S…

axios案例应用

1、Spring概述 Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架&#xff0c;以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核&#xff0c;提供了展现层 Spring MVC 和持久层。Spring JDBC 以及业务层事务管理等众多…

day16|二叉树的属性

相关题目 ● 104.二叉树的最大深度 559.n叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数 二叉树的深度与高度 如图&#xff0c; 二叉树的深度表示&#xff1a;任意一个叶子节点到根节点的距离&#xff0c;是从上往下计数的&#xff0c;因此使用前序遍历…