ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Sentinel Dashboard 1.8.6集成Nacos改造:实现网关限流规则持久化

Sentinel Dashboard 1.8.6集成Nacos改造:实现网关限流规则持久化 简介面向微服务架构开发与运维人员这份资源是 Sentinel Dashboard 1.8.6 与 Nacos 集成、对接 Gateway 限流的参考实现。核心思路是在 resources 下的 application.properties 中修改 Nacos 连接参数使流控规则能动态同步到 Nacos从而通过控制台统一管理下游网关的限流策略适合需要落地服务治理方案的中高级工程师。压缩包共 568 个文件、约 26.25MB包括 151 个 Java 源文件、170 个 class 编译类覆盖 GatewayFlowRuleController、ParamFlowRuleController、ClusterConfigService 等关键控制器与集群配置服务同时含有前端控制台所需的 js、html、css 以及 xml、properties 等配置便于结合源码理解规则下发、参数流控和集群管控的实现细节。已有 194 人学习目录结构相对完整既可直接部署体验也可作为二次开发或异常排查的参考。 说起 Sentinl Dashboard 和 Nacos 的集成做微服务的同学应该都不陌生但落在 1.8.6 这个版本上想把 Dashboard 当规则管理后台、还要对接 Gateway 的限流规则默认是做不到的。默认情况下规则全存在本地内存里Dashboard 一重启规则就没了网关服务的限流规则也跟 Dashboard 完全脱节。这篇文章我会把整套改造过程完整捋一遍从为什么需要做持久化到源码级改造 Dashboard再到 Gateway 接入 Nacos 数据源和限流规则下发适合正在用 Spring Cloud Alibaba Gateway Nacos 做微服务网关限流、又不想手动维护一堆规则文件的同学参考。1. 为什么把 Sentinel Dashboard 1.8.6 绑到 Nacos 上1.1 原生 Dashboard 的规则存储局限默认情况下Sentinel Dashboard 的所有规则都存在 JVM 内存里。你在页面上加了一条流控规则数据落在服务端的内存 Map 中客户端上报心跳后Dashboard 再从内存里把规则列表拼出来渲染到前端。这套机制在单机演示时没问题可到了生产环境就是大麻烦Dashboard 一重启规则全没。更难受的是如果团队里同时有多个环境、多套网关规则只能一台台手工配置根本没有统一的版本概念。我最早在测试环境用原生 Dashboard 配了十几条 Gateway 限流规则一次服务器迁移全丢了从那以后我就下定决心把规则存储从内存换到 Nacos。1.2 Nacos 作为规则存储能带来什么规则持久化到 Nacos 之后第一个收益就是规则不再跟着 Dashboard 的进程走。Nacos 本身就是配置中心天然提供配置版本管理、历史变更记录、灰度发布这些能力线上如果发现某条限流规则太激进直接把 Nacos 里的配置回滚到上一版就行不需要重新在页面上一遍遍点。第二个收益是客户端可以主动订阅数据源。Gateway 服务启动时会从 Nacos 拉规则后续 Nacos 配置变更也会实时推给网关限流阈值调整从分钟级变成秒级生效。第三个收益是 Dashboard 可以随时重启甚至替换成新版本只要 Nacos 里的规则还在启动完成后自动把规则拉回来业务无感知。1.3 为什么特别强调对接 Gateway 限流把限流放在网关层主要是为了在流量进入后端服务之前就把它拦住。假如只在某个订单服务上配限流请求已经穿过了网关、路由到了业务服务这时候再拒绝流量服务的线程池和数据库连接已经被占用了。网关限流是在入口做拦截一个路由规则能保护后面所有下游服务。但 Gateway 的规则在 Sentinel Dashboard 里是单独管理的普通流控规则对应的FlowRule和网关流控规则GatewayFlowRule走的是两套 Controller持久化时也要分别实现 provider 和 publisher。如果只改了普通流控规则的持久化Gateway 规则那块依然回退到内存存储正好是很多教程里没讲透的地方。2. 版本选型与基础环境准备2.1 依赖版本组合参考我在改造时采用的版本组合如下实测能稳定跑通组件版本说明Spring Boot2.5.12不要用 3.xSentinel 1.8.6 对 Spring Boot 3 支持不完整Spring Cloud Alibaba2021.0.1.0包含 Sentinel 相关 starterNacos Server2.2.1用 2.x1.x 的鉴权和配置推送体验差很多sentinel-dashboard1.8.6需要自己源码改造sentinel-datasource-nacos1.8.6Gateway 客户端侧接入这个组合里最需要守住的一点是 Spring Cloud Alibaba 版本别追新。有些同学一看有 2023 版本就直接用结果 Gateway 集成 Sentinel 的那套 starter 包路径都变了后续排查成本很高。2.2 Nacos 服务启动与核对先从 Nacos 官网下载对应版本解压后直接执行启动脚本。Linux / macOS 下是startup.sh -m standaloneWindows 下是startup.cmd -m standalone。启动完成后访问http://localhost:8848/nacos默认账号密码是nacos/nacos能正常登录说明服务没问题。生产环境建议把 Nacos 的配置存到 MySQL不然 Nacos 自身一重启你辛辛苦苦攒的命名空间、配置、用户数据一样会丢这点很多人容易忽略。2.3 改造前先捋清楚规则数据流在动手改代码之前建议先把规则流转方向在脑子里过一遍。Dashboard 页面点保存Controller 拿到请求后调用的是 publisherpublisher 把规则序列化成 JSON 写到 Nacos 的指定 dataIdGateway 客户端通过sentinel-datasource-nacos订阅同一个 dataIdNacos 配置一变客户端本地规则自动刷新后面的请求就按新规则执行。整个过程里 Dashboard 只是编辑器和写入器它不再是规则的唯一持有者。理解了这个数据流后面看代码时就不会被一堆 Controller 绕晕。3. Dashboard 集成 Nacos 的源码改造实录3.1 源码准备与改造目标先把仓库拉下来切到1.8.6的 tag改造只涉及sentinel-dashboard这一个模块。在 1.8.6 版本里规则存储已经抽象出了DynamicRuleProviderT和DynamicRulePublisherT两个接口默认是内存实现。我们新增一套 Nacos 实现再把 Controller 里注入的内存实现替换成 Nacos 实现改动范围很集中。注意1.8.6 和旧版本不同FlowControllerV1仍然直接操作内存FlowControllerV2才走 provider / publisher 扩展点。所以改造时要确认前端页面调用的是哪个 Controller如果 V1 不走扩展点后面规则写了也没效果。3.2 引入 Nacos 客户端依赖在sentinel-dashboard/pom.xml中增加dependency groupIdcom.alibaba.nacos/groupId artifactIdnacos-client/artifactId version2.2.1/version /dependency如果 Nacos 服务端用了更老的版本2.x 客户端大多数情况下也能兼容但建议尽量对齐版本。3.3 规则 dataId 与分组规划统一规则 dataId 和 groupId 非常重要。我一般按应用名-规则类型命名 dataIdgroup 统一叫SENTINEL_GROUP。放在常量类里Dashboard 和 Gateway 两端用同一套约定避免对不上。比如应用名gateway-service那普通流控规则就是gateway-service-flow-rules网关流控规则是gateway-service-gateway-flow-rulesAPI 分组是gateway-service-gateway-api-rules。3.4 Provider 与 Publisher 实现以普通流控规则为例读取规则的 Provider 长这样Component(flowRuleNacosProvider) public class FlowRuleNacosProvider implements DynamicRuleProviderListFlowRuleEntity { Autowired private ConfigService configService; Override public ListFlowRuleEntity getRules(String appName) throws Exception { String dataId appName NacosConfigUtil.FLOW_DATA_ID_POSTFIX; String rules configService.getConfig(dataId, NacosConfigUtil.GROUP_ID, 3000); if (StringUtil.isEmpty(rules)) { return new ArrayList(); } return JSON.parseArray(rules, FlowRuleEntity.class); } }写入规则的 Publisher 长这样Component(flowRuleNacosPublisher) public class FlowRuleNacosPublisher implements DynamicRulePublisherListFlowRuleEntity { Autowired private ConfigService configService; Override public void publish(String app, ListFlowRuleEntity rules) throws Exception { AssertUtil.notEmpty(app, app name cannot be empty); if (rules null) { return; } configService.publishConfig( app NacosConfigUtil.FLOW_DATA_ID_POSTFIX, NacosConfigUtil.GROUP_ID, JSON.toJSONString(rules) ); } }网关流控规则和 API 分组规则也是同样的套路只是实体类换成GatewayFlowRuleEntity和ApiDefinitionEntitydataId 后缀换成对应的常量。建议直接照着FlowRule的实现复制出来改不要试图省事搞一个通用类后面调试时最简单的代码反而最不容易出错。3.5 注入替换与编译打包在FlowControllerV2里默认注入的是flowRuleProvider和flowRulePublisher要把注入点换成flowRuleNacosProvider和flowRuleNacosPublisher。GatewayFlowRuleController和GatewayApiController同理。改完后执行mvn clean package生成新的 Dashboard Jar 包。启动时记得配置 Nacos 地址我一般用环境变量SENTINEL_NACOS_ADDR启动命令大致如下java -jar sentinel-dashboard.jar \ -Dserver.port8080 \ -Dcsp.sentinel.dashboard.serverlocalhost:8080 \ -Dproject.namesentinel-dashboard \ -Dsentinel.nacos.serverAddrlocalhost:8848注意ConfigService的初始化要在 Dashboard 启动时就完成建议在NacosConfigUtil中提供初始化方法用静态块或启动监听器创建避免第一次访问页面时才创建导致规则读取失败。4. Gateway 接入 Sentinel 并打通限流4.1 网关工程依赖在 Gateway 工程的 pom.xml 里加上dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-sentinel-gateway/artifactId /dependency dependency groupIdcom.alibaba.csp/groupId artifactIdsentinel-datasource-nacos/artifactId version1.8.6/version /dependency第一个 starter 提供 Sentinel 基础能力第二个负责把 Sentinel 的过滤器挂到 Spring Cloud Gateway 的过滤器链上第三个是 Nacos 数据源。三个缺一个限流链路都不完整。4.2 配置数据源指向 Nacos在application.yml中配置spring: application: name: gateway-service cloud: sentinel: transport: dashboard: localhost:8080 port: 8719 datasource: flow: nacos: server-addr: localhost:8848 dataId: gateway-service-flow-rules groupId: SENTINEL_GROUP >[ { id: 1, appName: gateway-service, apiName: order_api, predicateItems: [ { pattern: /order/**, matchStrategy: 0 } ] } ]matchStrategy为 0 表示精确匹配前缀1 表示正则匹配。之后在 Dashboard 的网关流控规则里资源名直接填order_api这样限流规则就跟具体的 Gateway 路由解耦了。路由后面怎么调整只要 API 前缀不变规则就不用动。4.4 验证限流效果全部配置好后先用单机压测工具快速验证。我习惯先配一条 QPS 阈值为 10 的网关规则再用ab或 Jmeter 发 100 个并发请求观察返回结果。命中限流时Sentinel 默认返回的是Blocked by Sentinel: FlowException配合自定义的BlockRequestHandler可以改成立即返回 JSON 错误体。这里提醒一下设置过低的阈值容易在压测时把自己手误限流出问题测试阶段建议从 50 或 100 开始往下压逐步观察曲线。5. 实战中踩过的坑与排查手册5.1 Dashboard 页面没有 Gateway 流控规则入口我在第一次改造完成后登录 Dashboard 发现只有“流控规则”“降级规则”这些菜单完全没有“网关流控规则”。原因是 1.8.6 的 Dashboard 前端菜单根据网关模式字段来控制而后端服务里 Gateway 相关 Controller 因为缺少依赖没有被加载。解决方案是前后端一起排查后端先确认GatewayFlowRuleController是否被扫描到前端确认导航菜单配置里网关相关的可见性条件是否满足。5.2 Nacos 里配置存在但网关限流不生效最典型的场景是 Dashboard 写的 dataId 是gateway-service-flow-rules网关的spring.cloud.sentinel.datasource里写的却是gateway-flow-rules两边对不上。另一个常见问题发生在 JSON 格式上FlowRuleEntity序列化时如果带了id、gmtModified这些额外字段客户端反序列化部分场景下会抛异常。我的做法是尽量用精简的 JSONpublisher 里只发布核心字段或者在客户端用统一的 JSON 解析配置。5.3 Dashboard 保存规则后 Nacos 里始终没有数据这种问题基本都出在 publisher 没有生效。常见原因有三个注入点还是默认的内存实现ConfigService初始化失败但异常被吞了以及publishConfig调用参数里 dataId 或 groupId 写了空值。排查时先看 Dashboard 启动日志有没有 Nacos 连接成功的记录再确认 Controller 里注入的 Bean 是哪个实现。5.4 Dashboard 重启后页面规则为空先说结论这是 provider 没生效的典型表现页面读取的规则仍然来自内存而不是 Nacos。检查点主要是FlowControllerV2的 provider 注入、前端请求路径是否真的打到了 V2。有些教程直接改 V1改完页面确实能读规则但 V1 底层没有走 provider等于绕过了持久化看着像成功实则白改。5.5 Dashboard 和 Gateway 都连上 Nacos 后出现规则覆盖这个坑比较隐蔽。它更多是使用习惯问题如果 Dashboard 和网关客户端各自从 Nacos 加载规则数据源是同一个理论上不会重复。但一旦有人在 Dashboard 页面保存规则Dashboard 会通过 publisher 把内存里的全量规则写回 Nacos如果内存规则和 Nacos 已有规则不一致就可能出现覆盖。建议把 Dashboard 侧的 Nacos 写入作为唯一写入源网关侧数据源只做订阅和动态刷新不要两边都维护同一份规则。6. 关于这套方案的一些个人心得6.1 规则模型尽量精简我在实际项目里有一个很深的体会FlowRuleEntity这种在 Dashboard 页面展示用的实体类直接序列化到 Nacos 虽然后端能解析但它包含了很多 UI 相关字段例如gmtModified、id、app等。网关客户端用sentinel-datasource-nacos反序列化时如果 JSON 里有这些多余字段在严格模式下会直接失败。建议在 publisher 里做一层转换或者干脆定义精简的 DTO只保留 Sentinel 规则真正需要的字段。6.2 生产环境用命名空间隔离如果公司有多个环境建议在 Nacos 里按环境建命名空间然后把SENTINEL_GROUP、规则 dataId 都放到对应命名空间下。这样测试环境的限流规则不会影响到生产环境也不会因为误操作互相覆盖。Dashboard 启动和 Gateway 配置里都要指定同一个命名空间踩过一次“测试环境规则覆盖生产”的坑后就再也回不去了。6.3 监控与告警不能只看 DashboardDashboard 只是规则管理台不是实时监控的唯一来源。Sentinel 的监控数据默认是 10 秒聚合一次推到 Dashboard如果 Dashboard 重启时间比较长这部分监控数据就会丢。建议把监控指标同时接到 Prometheus / Grafana限流规则持久化解决了规则丢失问题但监控数据还得靠另外一套链路保底。最后分享一个实在的建议如果你所在的项目组要从 0 搭建网关限流不要先把所有规则一次性配好先挑一个非核心接口把整条链路跑通——Dashboard 写规则、Nacos 存储、Gateway 订阅、压测出效果再慢慢丰富规则。这条路我走过一遍最费时间的从来不是代码而是版本兼容和数据链路理解。希望这篇实战记录能帮你少踩几个我踩过的坑。本文还有配套的精品资源点击获取
返回列表