尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Spring Cloud Alibaba生态探索:Gateway+Nacos动态路由配置与验证

Spring Cloud Alibaba生态探索:Gateway+Nacos动态路由配置与验证 1. 为什么要把路由从 YAML 搬到 NacosSpring Cloud Alibaba 微服务里Gateway 是所有流量的入口Nacos 既是注册中心也是配置中心。很多同学第一次搭 Gateway 时习惯把spring.cloud.gateway.routes直接写在application.yml里本地跑得挺顺一上线就发现问题每加一条路由、改一个StripPrefix参数都得改配置文件、重新打包、重启网关。网关一重启所有经过它的请求都会短暂 502灰度发布、临时限流、新服务上线这些高频操作根本扛不住。动态路由要解决的就是这件事路由规则不再写死在网关进程里而是放到 Nacos 配置中心网关启动时拉一次之后监听这个配置Nacos 上一改网关内存里的路由表立刻刷新不用重启。适合谁正在用 Spring Cloud Alibaba 做微服务、已经跑通 Nacos 注册发现、想让网关具备“改配置即生效”能力的后端同学。这篇就带你从零走一遍完整闭环Nacos 里放路由 JSON、Gateway 监听刷新、改配置后验证新路由生效、旧路由失效。我试过把这套流程在本地和测试环境各跑一遍最容易翻车的不是代码而是 Nacos 的dataId、group和配置格式对不上。下面按可复制的顺序来。2. TaoToken 前置先把模型调用和 Key 准备好这套动态路由本身不依赖大模型但你在调试网关、写路由断言、排查 502 时如果想让 AI 帮你读日志、生成RouteDefinitionJSON、解释RefreshRoutesEvent的触发链路就需要一个稳定的模型入口。我平时用 TaoToken 来做这类辅助它的 API 地址是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。你需要先拿到 API Key入口在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。拿到之后接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面写了不同语言怎么填 base_url 和 model。如果你只是想先验证模型通不通可以直接用模型对话页https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite。要是你打算长期用 AI 辅助写代码、跑 Agent 任务Coding Plan 更划算https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。注意TaoToken 在这里的角色是“帮你读日志、生成配置、解释报错”的辅助工具不是网关组件本身。网关动态路由的核心仍然是 Nacos Spring Cloud Gateway。3. 可复制配置依赖、bootstrap 与动态路由组件3.1 Maven 依赖补齐 Nacos Config在网关模块的pom.xml里除了spring-cloud-starter-gateway和spring-cloud-starter-alibaba-nacos-discovery必须再加一个spring-cloud-starter-alibaba-nacos-config否则网关读不到 Nacos 配置中心的配置。dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency版本对齐用spring-cloud-alibaba-dependencies统一管理比如2.2.1.RELEASE配Hoxton.SR1别自己乱填版本号否则NacosFactory可能找不到类。3.2 bootstrap.yml 必须存在Nacos Config 的server-addr要写在bootstrap.yml里因为它在应用上下文引导阶段就要加载优先级高于application.yml。很多人只写application.yml结果启动时报“无法连接 Nacos 配置中心”。server: port: 9000 spring: application: name: spring-cloud-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:88483.3 动态路由服务负责增删和发布事件这个类做三件事把RouteDefinition写进RouteDefinitionWriter、记录已添加的路由 id、发布RefreshRoutesEvent让网关刷新。Service public class NacosDynamicRouteService implements ApplicationEventPublisherAware { Autowired private RouteDefinitionWriter routeDefinitionWriter; private ApplicationEventPublisher applicationEventPublisher; private static final ListString ROUTE_LIST new ArrayList(); public void clearRoute() { for (String id : ROUTE_LIST) { this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); } ROUTE_LIST.clear(); } public void addRoute(RouteDefinition definition) { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); ROUTE_LIST.add(definition.getId()); } public void publish() { this.applicationEventPublisher.publishEvent( new RefreshRoutesEvent(this.routeDefinitionWriter)); } Override public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { this.applicationEventPublisher publisher; } }3.4 动态路由组件启动初始化 监听 NacosdataId和group要和 Nacos 控制台里创建的配置完全一致这里用spring-cloud-gateway-router和DEFAULT_GROUP。Component public class NacosDynamicRoute { private static final Logger log LoggerFactory.getLogger(NacosDynamicRoute.class); private String dataId spring-cloud-gateway-router; private String group DEFAULT_GROUP; Value(${spring.cloud.nacos.config.server-addr}) private String serverAddr; Autowired private NacosDynamicRouteService nacosDynamicRouteService; PostConstruct public void init() { try { ConfigService configService NacosFactory.createConfigService(serverAddr); String configInfo configService.getConfig(dataId, group, 5000); ListRouteDefinition list JSON.parseArray(configInfo, RouteDefinition.class); for (RouteDefinition definition : list) { nacosDynamicRouteService.addRoute(definition); } } catch (Exception e) { log.error(初始化网关路由失败, e); } dynamicRouteByNacosListener(); } public void dynamicRouteByNacosListener() { try { ConfigService configService NacosFactory.createConfigService(serverAddr); configService.addListener(dataId, group, new Listener() { Override public void receiveConfigInfo(String configInfo) { nacosDynamicRouteService.clearRoute(); ListRouteDefinition list JSON.parseArray(configInfo, RouteDefinition.class); for (RouteDefinition definition : list) { nacosDynamicRouteService.addRoute(definition); } nacosDynamicRouteService.publish(); } Override public Executor getExecutor() { return null; } }); } catch (NacosException e) { log.error(监听 Nacos 路由配置失败, e); } } }3.5 Nacos 里的路由 JSON 骨架在 Nacos 控制台新建配置Data ID 填spring-cloud-gateway-routerGroup 填DEFAULT_GROUP格式选 JSON。内容如下注意不要加注释JSON 不允许注释。[ { id: goods-route, predicates: [ { name: Path, args: { pattern: /api-v1/** } } ], filters: [ { name: StripPrefix, args: { parts: 1 } } ], uri: lb://goods-service } ]uri用lb://前缀表示走 Nacos 服务发现负载均衡goods-service是注册在 Nacos 里的服务名。StripPrefix1会把/api-v1/xxx去掉第一段转发给后端时变成/xxx。4. 验证请求改 Nacos 配置后路由是否即时生效启动网关观察日志里有没有打印“获取网关当前设置”和路由定义。然后用 curl 打网关端口curl -i http://127.0.0.1:9000/api-v1/goods/list如果后端goods-service正常应该返回 200 和业务数据。这一步证明初始路由加载成功。接着做动态验证在 Nacos 控制台把pattern从/api-v1/**改成/api-v2/**或者把id改成goods-route-v2发布配置。网关日志会立刻出现监听回调打印新的路由定义。此时再请求curl -i http://127.0.0.1:9000/api-v2/goods/list应该返回 200。再请求旧路径curl -i http://127.0.0.1:9000/api-v1/goods/list应该返回 404说明旧路由已经被clearRoute()删掉新路由生效。整个过程网关进程没有重启这就是动态路由闭环。提示如果你在 Nacos 里改的是uri指向的服务名记得确认目标服务已经注册到同一个 Nacos 命名空间否则会报Unable to find instance for xxx。5. 本篇常见错排查报错一configService.getConfig返回 null启动时路由为空。先确认dataId、group、命名空间三者一致。Nacos 默认命名空间是public如果你在控制台建配置时选了别的命名空间代码里也要加namespace参数。另外bootstrap.yml里的server-addr不能写成http://前缀直接写IP:8848。报错二改了 Nacos 配置网关日志没有监听回调。检查addListener是否真的执行到了。常见原因是PostConstruct里抛异常被 catch 吞掉后面的dynamicRouteByNacosListener()没执行。把 catch 里的日志级别调到 error 并打印堆栈先看初始化那一步有没有成功。报错三新路由生效了但请求 503。lb://goods-service走的是服务发现503 通常表示网关找不到实例。去 Nacos 服务列表确认goods-service是否在线以及网关和服务是否在同一个命名空间、同一个 group。如果服务在但网关的spring.cloud.nacos.discovery没配也会找不到。报错四JSON 解析失败JSON.parseArray抛异常。Nacos 配置里千万别写//注释也别用单引号。RouteDefinition的字段名是predicates、filters、uri、id大小写敏感。建议在本地用 JSON 校验工具先过一遍再贴进 Nacos。报错五RefreshRoutesEvent发布了但路由没变。确认RouteDefinitionWriter注入的是 Gateway 自动配置的那个 Bean不要自己 new。另外clearRoute()里删除的是ROUTE_LIST里记录的 id如果第一次加载时 id 没记录进去旧路由就删不掉会出现新旧路由同时存在的情况。6. 继续把动态路由接进你的编码流程走到这里你已经完成了一次完整的 Nacos 驱动 Gateway 动态路由验证配置放 Nacos、网关监听刷新、改配置即时生效、旧路由自动失效。接下来可以做的扩展包括把路由配置按环境拆成不同group、在 Nacos 里做灰度路由、结合Coding Plan让 AI 帮你批量生成RouteDefinitionJSON 并做格式校验。如果你在接入或排障过程中卡在某个报错优先去 API Keys 页面确认 Key 状态https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite再对照接入文档检查 base_url 和请求格式https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。想先验证模型能不能正常返回用模型对话页最快https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite。长期写代码、跑 Agent 的话Coding Plan 的入口在这里https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。
返回列表