)
1. 为什么需要Sentinel与Nacos深度整合第一次接触Sentinel时最让我头疼的就是规则配置的管理问题。默认情况下通过Sentinel控制台配置的规则都只保存在内存中一旦应用重启所有精心配置的流控规则、熔断规则就全没了。这就像用铅笔在纸上做笔记橡皮擦一擦就消失得无影无踪。在实际生产环境中这种内存模式显然不够用。想象一下你花了半天时间调整好的限流参数因为服务器例行重启就全部丢失这种体验实在太糟糕。更麻烦的是当你有多个服务实例时如何保证所有实例的规则配置都保持一致手动一个个配置显然不现实。这时候Nacos就派上用场了。Nacos作为配置中心天生就适合存储这类需要持久化和动态分发的配置信息。把Sentinel的规则配置存到Nacos中至少能解决三个痛点持久化存储规则不会因为应用重启而丢失动态同步修改规则后能实时推送到所有服务实例集中管理所有规则在一个地方统一查看和修改2. Sentinel规则推送的三种模式在动手改造之前我们需要先搞清楚Sentinel规则推送的工作原理。根据官方文档规则推送主要有三种模式2.1 原始模式最基础但最不实用这是Sentinel默认的工作方式。控制台通过API直接把规则推送到客户端内存中简单粗暴。优点是不依赖任何外部组件缺点是规则只存在于内存应用重启就没了。就像在沙滩上写字海浪一来就冲走了。2.2 Pull模式折中方案客户端定期从某个地方比如数据库、文件拉取规则更新。这种方式实现了规则持久化但实时性较差。就像你设置了一个闹钟每小时检查一次邮箱重要邮件可能要等很久才能看到。2.3 Push模式生产环境推荐这是我们今天要重点改造的模式。规则中心如Nacos统一管理所有配置控制台负责把规则推送到规则中心客户端监听规则中心的变化。这种架构保证了规则的实时性和一致性是生产环境的首选方案。3. 改造前的准备工作3.1 环境准备在开始编码前我们需要准备好以下环境JDK 1.8Spring Boot 2.3.xSpring Cloud Hoxton.SR12Spring Cloud Alibaba 2.2.9.RELEASENacos Server 2.0.2Sentinel 1.8.5这些版本经过我的实测可以稳定工作如果你用其他版本可能需要做一些适配调整。3.2 获取Sentinel控制台源码官方源码可以从GitHub获取git clone https://github.com/alibaba/Sentinel.git如果访问GitHub有困难也可以使用我改造好的Gitee镜像git clone https://gitee.com/kerwin_code/kerwin-sentinel-1.8.5.git3.3 客户端配置在应用服务中我们需要添加sentinel-datasource-nacos依赖dependency groupIdcom.alibaba.csp/groupId artifactIdsentinel-datasource-nacos/artifactId /dependency然后在配置文件中设置Nacos数据源spring: cloud: sentinel: eager: true datasource: ds-flow: nacos: server-addr: 127.0.0.1:8848 dataId: myapp-flow-rules >dependency groupIdcom.alibaba.csp/groupId artifactIdsentinel-datasource-nacos/artifactId !-- 去掉这行 -- !-- scopetest/scope -- /dependency4.2 实现Nacos规则提供者和发布者我们需要为每种规则类型创建对应的Nacos操作类。以流控规则为例Component(flowRuleNacosProvider) public class FlowRuleNacosProvider implements DynamicRuleProviderListFlowRuleEntity { Autowired private ConfigService configService; Autowired private ConverterString, ListFlowRuleEntity converter; Override public ListFlowRuleEntity 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); } }对应的发布者实现Component(flowRuleNacosPublisher) public class FlowRuleNacosPublisher implements DynamicRulePublisherListFlowRuleEntity { Autowired private ConfigService configService; Autowired private ConverterListFlowRuleEntity, String converter; Override public void publish(String app, ListFlowRuleEntity rules) throws Exception { configService.publishConfig(app NacosConfigUtil.FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, converter.convert(rules), ConfigType.JSON.getType()); } }4.3 改造流控控制器原来的FlowControllerV1需要调整主要修改ruleProvider和rulePublisher的注入RestController RequestMapping(value /v1/flow) public class FlowControllerV1 { Autowired Qualifier(flowRuleNacosProvider) private DynamicRuleProviderListFlowRuleEntity ruleProvider; Autowired Qualifier(flowRuleNacosPublisher) private DynamicRulePublisherListFlowRuleEntity rulePublisher; // 其他方法保持不变 }关键是在publishRules方法中现在改为调用Nacos发布器private void publishRules(String app) throws Exception { ListFlowRuleEntity rules repository.findAllByApp(app); rulePublisher.publish(app, rules); }4.4 改造熔断降级控制器熔断规则的改造思路和流控规则类似这里就不重复贴代码了。主要区别在于使用不同的Data ID后缀-degrade-rules处理的是DegradeRuleEntity而不是FlowRuleEntity5. 测试与验证改造完成后启动Sentinel控制台和应用服务。现在当你新增或修改规则时可以到Nacos控制台查看规则已经以JSON格式持久化存储了。一个典型的流控规则在Nacos中是这样的[{ app: myapp, resource: /api/test, limitApp: default, grade: 1, count: 100, strategy: 0, controlBehavior: 0, clusterMode: false }]6. 改造过程中的坑与解决方案在实际改造中我遇到了几个典型问题6.1 版本兼容性问题最初我尝试用Spring Cloud Alibaba 2021.x版本发现和Sentinel 1.8.5存在兼容性问题。后来回退到Hoxton.SR12才稳定下来。建议大家在选择版本时先查看官方提供的版本兼容表。6.2 Nacos配置格式问题Sentinel对规则JSON的格式要求比较严格特别是app字段必须和服务名一致。有次调试了半天才发现是因为app字段写错了导致规则无法正常加载。6.3 多环境配置隔离生产环境中我们通常需要用namespace来隔离不同环境的配置。这时要确保Sentinel控制台和客户端使用相同的namespaceNacos中对应的namespace已经存在7. 扩展思考目前我们只实现了流控和熔断规则的持久化实际上Sentinel还支持多种规则类型热点参数规则param-flow系统保护规则system授权规则authority这些规则的改造思路大同小异找到对应的Controller和RuleManager替换成Nacos的Provider和Publisher即可。对于更复杂的场景比如网关限流规则原理也是类似的。关键在于找到规则的处理入口通常是以Gateway开头的Controller类。