当前位置: 首页 > news >正文

spring cloud sentinel 动态规则配置

Sentinel 允许在运行时根据不同的需求动态调整限流、熔断等规则。通过动态规则扩展,你可以实现:

  • 自动调整:根据业务流量的变化自动调整规则。
  • 外部配置支持:规则可以从数据库、配置中心(如 Nacos、Apollo)或者文件等外部来源加载。
  • 热更新:不需要重启应用,规则就能实时生效。

Sentinel 提供两种方式修改规则:

  • 通过 API 直接修改 (loadRules)
  • 通过 DataSource 适配不同数据源修改

通过 API 修改比较直观,可以通过以下几个 API 修改不同的规则:

FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控规则
DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降级规则

手动修改规则(硬编码方式)一般仅用于测试和演示,生产上一般通过动态规则源的方式来动态管理规则。

DataSource 扩展

DataSource 扩展常见的实现方式有:

  • 拉模式:客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件。这样做的方式是简单,缺点是无法及时获取变更;
  • 推模式:规则配置中心统一推送,客户端通过注册监听器的方式时刻监听变化,sentinel支持ZooKeeper, Redis, Nacos, Apollo, etcd等配置中心。这种方式有更好的实时性和一致性保证。

上述集中数据源扩展方式,sentinel是支持springboot自动装配的,下面以文件和nacos配置中心的形式来进行演示流量控制规则动态配置。

首先添加数据源扩展依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-extension</artifactId>
</dependency>
文件模式

定义一个规则配置文件FlowRule.json放到resources下

[{"resource": "add","controlBehavior": 0,"count": 3.0,"grade": 1,"limitApp": "default","strategy": 0}
]

一个流量配置规则重要属性如下:

Field说明默认值
resource资源名,资源名是限流规则的作用对象
count限流阈值
grade限流阈值类型,QPS 或线程数模式QPS 模式
limitApp流控针对的调用来源default,代表不区分调用来源
strategy调用关系限流策略:直接、链路、关联根据资源本身(直接)
controlBehavior流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流直接拒绝

配置文件配置

spring:cloud:sentinel:transport:port: 8719dashboard: localhost:8080datasource:ds1:file:file: classpath:FlowRule.json #指定规则文件位置data-type: json #指定文件格式rule-type: flow #指定规则类型charset: utf-8 #指定文件编码

sentinel的datasource配置支持是Map<String, DataSourcePropertiesConfiguration>类型,可以支持同时配置多个数据源。不同的数据源有几个共同的配置项:

data-type: 数据格式类型,默认json

rule-type:规则类型,flow,grade,system等值可配置,具体项可查看RuleType枚举类。

converterClass:配置数据格式化处理类,默认json使用的jackson的ObjectMapper进行解析。

Nacos数据源

nacos添加额外依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

配置文件配置

spring:cloud:sentinel:datasource:ds2:nacos:serverAddr: localhost:8848namespace: sentinelgroupId: flowtestdataId: sentinel_system_flow_rule.jsondataType: jsonruleType: flow

nacos数据源配置和其作为配置中心信息差不多,nacos的连接信息,配置资源文件位置。

手动编码配置

除了使用springboot自动装配扩展数据源,也可以通过手动编码的方式进行自定义配置。使用FlowRuleManager.register2Property()方法进行手动注册数据源,例如手动注册一个文件数据源

//读取配置文件内容
ClassLoader classLoader = getClass().getClassLoader();
String flowRulePath = URLDecoder.decode(classLoader.getResource("FlowRule.json").getFile(), "UTF-8");
//定义converter
Converter<String, List<FlowRule>> flowRuleListParser = s -> JSON.parseObject(s,new TypeReference<List<FlowRule>>(){});
//构造FileRefreshableDataSource
FileRefreshableDataSource<List<FlowRule>> flowRuleDataSource = new FileRefreshableDataSource<>(flowRulePath, flowRuleListParser);
//注册数据源
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

手动注册数据源时候一定要注意代码执行顺序,否则执行过早可能在sentinel的控制台看不到配置规则信息,最好在容器初始化完成后执行,也可以使用sentinel自带的InitFunc的spiloader扩展方式。

动态规则扩展的原理

所有的动态数据源扩展最后都是通过FlowRuleManager.register2Property将数据源注册到规则管理器上。

FlowRuleManager.register2Property()

    public static void register2Property(SentinelProperty<List<FlowRule>> property) {AssertUtil.notNull(property, "property cannot be null");synchronized (LISTENER) {RecordLog.info("[FlowRuleManager] Registering new property to flow rule manager");currentProperty.removeListener(LISTENER);property.addListener(LISTENER);currentProperty = property;}}

这里会给property添加一个listenner。这里以文件类型扩展源来看下。

先来看FileRefreshableDataSource内部动态刷新机制,其实很简单就是一个定时器检测文件变化。FileRefreshableDataSource继承抽象类AutoRefreshDataSource,其构造函数会启动定时器。

AutoRefreshDataSource#startTimerService()

    private void startTimerService() {//初始化线程池service = Executors.newScheduledThreadPool(1,new NamedThreadFactory("sentinel-datasource-auto-refresh-task", true));service.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {try {//文件是否有变化if (!isModified()) {return;}//如果有变化从新从文件读取规则数据T newValue = loadConfig();//调用updateValue方法触发规则更新getProperty().updateValue方法触发规则更新(newValue);} catch (Throwable e) {RecordLog.info("loadConfig exception", e);}}}, recommendRefreshMs, recommendRefreshMs, TimeUnit.MILLISECONDS);}

这里定时周期默认在FileRefreshableDataSource有常量DEFAULT_REFRESH_MS=3000,3秒检测一次。

isModified()在FileRefreshableDataSource实现就是根据文件的修改时间来判断file.lastModified()。

最重要的updateValue()方法,这里的property实例是DynamicSentinelProperty类型,

DynamicSentinelProperty#updateValue()

    public boolean updateValue(T newValue) {if (isEqual(value, newValue)) {return false;}RecordLog.info("[DynamicSentinelProperty] Config will be updated to: {}", newValue);value = newValue;for (PropertyListener<T> listener : listeners) {listener.configUpdate(newValue);}return true;}

这里看到会拿出Property中所有的listener依次调用configUpdate方法。listener的设置在我们第一步注册数据源到FlowRuleManager里就设置了。这里listener的类型是FlowPropertyListener。

FlowRuleManager.FlowPropertyListener.configUpdate()

public synchronized void configUpdate(List<FlowRule> value) {Map<String, List<FlowRule>> rules = FlowRuleUtil.buildFlowRuleMap(value);if (rules != null) {flowRules = rules;}RecordLog.info("[FlowRuleManager] Flow rules received: {}", rules);
}

最后将flowRule更新到内存中。

自动装配数据源原理

在sentinel的自动装配类SentinelAutoConfiguration中会初始化数据源处理类SentinelDataSourceHandler。该handler实现了SmartInitializingSingleton接口,在容器初始化完成后会调用afterSingletonsInstantiated()方法。

SentinelDataSourceHandler#afterSingletonsInstantiated

	public void afterSingletonsInstantiated() {sentinelProperties.getDatasource()//循环处理所有配置的datasource.forEach((dataSourceName, dataSourceProperties) -> {try {List<String> validFields = dataSourceProperties.getValidField();if (validFields.size() != 1) {log.error("[Sentinel Starter] DataSource " + dataSourceName+ " multi datasource active and won't loaded: "+ dataSourceProperties.getValidField());return;}AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties.getValidDataSourceProperties();abstractDataSourceProperties.setEnv(env);abstractDataSourceProperties.preCheck(dataSourceName);//将解析验证后数据源信息作为一个bean注册到容器中registerBean(abstractDataSourceProperties, dataSourceName+ "-sentinel-" + validFields.get(0) + "-datasource");}catch (Exception e) {log.error("[Sentinel Starter] DataSource " + dataSourceName+ " build error: " + e.getMessage(), e);}});}

registerBean()方法

	private void registerBean(final AbstractDataSourceProperties dataSourceProperties,String dataSourceName) {BeanDefinitionBuilder builder = parseBeanDefinition(dataSourceProperties, dataSourceName);this.beanFactory.registerBeanDefinition(dataSourceName,builder.getBeanDefinition());// init in SpringAbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory.getBean(dataSourceName);// register property in RuleManagerdataSourceProperties.postRegister(newDataSource);}

dataSourceProperties.postRegister()

	public void postRegister(AbstractDataSource dataSource) {switch (this.getRuleType()) {case FLOW:FlowRuleManager.register2Property(dataSource.getProperty());break;case DEGRADE:DegradeRuleManager.register2Property(dataSource.getProperty());break;...}}

这里看到最后也是通过FlowRuleManager.register2Property()将数据源注册到规则管理器中。

http://www.dtcms.com/a/303998.html

相关文章:

  • css3之三维变换详说
  • Windows系统ffmpeg.dll丢失怎么办?从错误分析到永久修复的完整流程
  • FPGA实现SRIO高速接口与DSP交互,FPGA+DSP异构方案,提供3套工程源码和技术支持
  • 处理订单过期但支付成功的系统设计:平衡用户体验与业务规则
  • 设计模式:中介者模式 Mediator
  • Oracle发布MCP Server,自然语言交互说“人话”
  • Kubernetes高级调度01
  • 设计模式十三:代理模式(Proxy Pattern)
  • pygame 模拟放飞气球
  • hive专题面试总结
  • Python 日期时间格式化与解析的瑞士军刀:`strftime()` 与 `strptime()`
  • 三、Linux用户与权限管理详解
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现各种食物的类型检测识别(C#代码UI界面版)
  • 学习嵌入式的第三十四天-数据结构-(2025.7.29)数据库
  • 小杰数据结构(one day)——心若安,便是晴天;心若乱,便是阴天。
  • 【数据可视化-75】北京密云区2025年7月暴雨深度分析:Python + Pyecharts 炫酷大屏可视化(含完整数据、代码)
  • Prometheus + Grafana + Micrometer 监控方案详解
  • Java:为什么需要通配符捕获(wildcard capture)
  • HbuilderX开发小程序
  • 定制开发开源AI智能名片S2B2C商城小程序对流量重构与价值提升的作用研究
  • 使用git托管keil工程
  • React函数组件的“生活管家“——useEffect Hook详解
  • C++:stack与queue的使用
  • 40+个常用的Linux指令——下
  • 基于变频与移相混合控制(PFM+PSM)的全桥LLC谐振变换器仿真模型
  • 机械臂抓取的无模型碰撞检测代码
  • 仿函数+优先级队列priority_queue的模拟实现
  • P2910 [USACO08OPEN] Clear And Present Danger S
  • AutoGen Agent 使用指南
  • 华为HCIA-Cloud Service 从知识到实践的学习指南