SpringCloud系列教程(十二):网关配置动态路由

除了token以外,还有一个很实用的功能就是把网关的路由配置放到nacos上,并且修改路由配置的时候,网关服务可以动态的更新,这样我们在调整网络配置的时候,就不用重启服务了。所以我们需要用到两个重要的类:NacosConfigManager和RouteDefinitionWriter,NacosConfigManager用来监听nacos上配置的变化,RouteDefinitionWriter会执行路由配置。

1、将原来写在application.yml中的路由配置信息迁移到nacos上,dataId定义为gateway-routes,这里要注意,原来在项目中yml文件解析的时候,会被SpringCloud层层解析后生成RouteDefinition,在这期间SpringCloud会去解析比如Path=/api/*这种形式,但是现在我们要自己解析,就要改成符合RouteDefinition的完全形式,这是一个小难点。

spring:cloud:gateway:routes:- id: nacos-client-demouri: lb://nacos-client-demopredicates: #断言,匹配访问的路径- name: Pathargs:pattern: /nacos-client-demo/api/**filters: # 过滤器- name: AddRequestHeaderargs:_genkey_0: headername_genkey_1: I am a header!- name: Myargs:_genkey_0: zhangsan_genkey_1: lisi_genkey_2: wangwu- id: open-feign-demouri: lb://open-feign-demopredicates:- name: Pathargs:pattern: /open-feign-demo/api/**

2、在application.yml中添加nacos的配置信息就可以了,并且我特意添加了两个参数,用来指明动态路由配置的dataId,这样以后改成其他的也方便。

spring:main:# gateway组件中的spring-boot-starter-webflux和springboot作为web项目启动必不可少的spring-boot-starter-web出现冲突web-application-type: reactiveapplication:name: gateway-democloud:gateway:nacos-data-id: gateway-routesnacos-group: devopsnacos:server-addr: 192.168.3.54:80username: nacospassword: nacosdiscovery:group: devopsnamespace: sitconfig:namespace: sitgroup: devopsconfig:import: nacos:${spring.application.name}?refresh=true
server:port: 8888

3、定义一个component类DynamicRouterLoader,继承ApplicationEventPublisherAware,网上很多教程没有继承,因为版本不同,我用新版的发现必须要用ApplicationEventPublisherAware发布一下才能让路由信息生效。

package com.mj.gateway.router;import cn.hutool.core.lang.Dict;
import cn.hutool.json.JSONUtil;
import cn.hutool.setting.yaml.YamlUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouterLoader implements ApplicationEventPublisherAware {//nacos配置管理器private final NacosConfigManager nacosConfigManager;//gateway路由规则写入器private final RouteDefinitionWriter writer;private ApplicationEventPublisher publisher;@Value("${spring.cloud.gateway.nacos-data-id:test}")private String dataId;@Value("${spring.cloud.gateway.nacos-group:test}")private String group;private final int timeout = 5000;//保存所有的路由idprivate final Set<String> routeIds = new HashSet<>();//PostConstruct表示实例化之后就会执行@PostConstructpublic void initRouteConfigListener() throws NacosException {//获取配置,服务启动的时候就要加载一次配置String config = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, timeout, new Listener() {@Overridepublic Executor getExecutor() {return null;}@Overridepublic void receiveConfigInfo(String config) {//配置变化时,重新加载配置updateConfig(config);}});//服务启动,加载配置updateConfig(config);}private void updateConfig(String config) {log.info("更新路由信息");//读取nacos中yaml配置Dict dict = YamlUtil.load(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(config.getBytes()))));//转换成Route对象List<RouteDefinition> routeDefinitions = JSONObject.parseObject(JSONUtil.toJsonStr(dict)).getJSONObject("spring").getJSONObject("cloud").getJSONObject("gateway").getJSONArray("routes").toList(RouteDefinition.class);//清理旧的路由规则routeIds.forEach(routeId -> writer.delete(Mono.just(routeId)).subscribe());//清空缓存routeIds.clear();// 遍历添加路由routeDefinitions.forEach(definition -> {//提交路由信息writer.save(Mono.just(definition)).subscribe();//缓存下记录,这样便于清除路由配置routeIds.add(definition.getId());});this.publisher.publishEvent(new RefreshRoutesEvent(this));}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher = applicationEventPublisher;}
}

DynamicRouterLoader在服务启动的时候就会实例化并且注入spring中,所以我们给方法initRouteConfigListener添加注解@PostConstruct,这样实例化一完成就会执行该方法。方法里使用NacosConfigManager获取到nacos的数据并做一次更新路由,这次更新是用来启动服务时初始化路由配置,再添加一个监听器,每次nacos修改都会触发这个监听器再次更新路由配置。更新路由其实有两个思路,思路1是能准确判断每次修改、删除的路由信息,然后分别执行update和delete,这就需要我们去做新旧版本配置的区分工作了,工作量比较大,思路2就是每次都清空所有路由,然后把最新版配置信息加载进去。思路2更简单一点,不过我没有测试过路由信息特别大的情况下会不会导致延迟,通常我们的微服务不至于多到会产生延迟,但是这里依旧要警惕,工作中如果发现数量真的很大了,就要多做一些压力测试。

4、重启服务,做测试:http://127.0.0.1:8888/nacos-client-demo/api/login?userid=123&username=zhangsan

这时候是正常的:

5、修改一下nacos上路由信息,把nacos-client-demo的路由直接删掉,保存服务一直正常运行,观察是否生效。

如果debug能发现监听器被调用了,日志也会打印,再调用接口就已经404了。

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

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

相关文章

R JSON 文件

R JSON 文件 引言 在当今的数据分析和处理领域&#xff0c;R语言作为一种功能强大的统计计算和图形展示工具&#xff0c;被广泛应用于各种数据分析任务中。随着大数据时代的到来&#xff0c;数据的格式和结构变得越来越多样化。JSON&#xff08;JavaScript Object Notation&a…

ES6 特性全面解析与应用实践

1、let let 关键字用来声明变量&#xff0c;使用let 声明的变量有几个特点&#xff1a; 1) 不允许重复声明 2) 块儿级作用域 3) 不存在变量提升 4) 不影响作用域链 5) 暂时性死区 6&#xff09;不与顶级对象挂钩 在代码块内&#xff0c;使用let命令声明变量之前&#x…

如何使用 Ollama 的 API 来生成聊天

如何使用 Ollama 的 API 来生成聊天 简介 生成聊天 生成聊天的示例 加载模型 卸载模型 简介 Ollama 提供了一个 RESTful API&#xff0c;允许开发者通过 HTTP 请求与 Ollama 服务进行交互。这个 API 覆盖了所有 Ollama 的核心功能&#xff0c;包括模型管理、运行和监控。本…

【学Rust写CAD】10 加法器

源码 // src/matrix/adder.rs/** 说明&#xff1a;连加计算中&#xff0c;为提高运行期效率&#xff0c;用该结构增加一个Const变量&#xff0c;方便单独合并所有Const类型&#xff0c;最后一步才有可能出现Const与Val的加法计算*/use std::ops::Add;use super::constant::{Co…

学到什么记什么(25.3.3)

Upload-labs 今日重新做了一下文件上传漏洞&#xff0c;这里第一题之前采用直接抓包改后缀名.jpg为.php&#xff0c;再写入一句话<?php phpinfo();?>然后放行&#xff0c;得到图片地址&#xff08;可复制&#xff09;&#xff0c;本来直接访问图片地址即可得到敏感信息…

el-table input textarea 文本域 自适应高度,切换分页滚动失效处理办法

场景&#xff1a; el-table 表格 需要 input类型是 textarea 高度是自适应&#xff0c;第一页数据都是单行数据 不会产生滚动条&#xff0c;但是第二页数据是多行数据 会产生滚动条&#xff0c; bug: 第一页切换到第二页 第二页滚动条无法展示 解决办法&#xff1a;直接修改样…

[杂学笔记] 封装、继承、多态,堆和栈的区别,堆和栈的区别 ,托管与非托管 ,c++的垃圾回收机制 , 实现一个单例模式 注意事项

文章目录 1.封装、继承、多态2. 堆和栈的区别3.指针和引用的区别4. 托管与非托管5. c的垃圾回收机制6. 实现一个单例模式 注意事项 1.封装、继承、多态 封装就是将数据和内部的方法封装到一个类中&#xff0c;对外隐藏内部实现细节&#xff0c;但是留下了公共接口提供给外部使…

【三维生成】StarGen:基于视频扩散模型的可扩展的时空自回归场景生成

标题&#xff1a;《StarGen: A Spatiotemporal Autoregression Framework with Video Diffusion Model for Scalable and Controllable Scene Generation》 项目&#xff1a;https://zju3dv.github.io/StarGen 来源&#xff1a;商汤科技、浙大CAD、Tetras.AI 文章目录 摘要一、…

【一个月备战蓝桥算法】递归与递推

字典序 在刷题和计算机科学领域&#xff0c;字典序&#xff08;Lexicographical order&#xff09;也称为词典序、字典顺序、字母序&#xff0c;是一种对序列元素进行排序的方式&#xff0c;它模仿了字典中单词的排序规则。下面从不同的数据类型来详细解释字典序&#xff1a; …

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(成功版)

【Linux】【网络】UDP打洞–&#xff1e;不同子网下的客户端和服务器通信&#xff08;成功版&#xff09; 根据上个文章的分析 问题可能出现在代码逻辑上面 我这里重新查找资料怀疑&#xff1a; 1 NAT映射可能需要多次数据包的发送才能建立。 2 NAT映射保存时间太短&#xff…

SpaCy处理NLP的详细工作原理及工作原理框图

spaCy处理NLP的详细工作原理及工作原理框图 spaCy处理NLP的详细工作原理 spaCy是一个基于Python的开源自然语言处理&#xff08;NLP&#xff09;库&#xff0c;它提供了一系列高效且易用的工具&#xff0c;用于执行各种NLP任务&#xff0c;如文本预处理、文本解析、命名实体识…

C++ Primer 动态数组

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

【Qt】ffmpeg照片提取、视频播放▲

目录 一、图像的成像原理&#xff1a; RGB成像原理&#xff1a; YUV成像原理&#xff1a; 二、多线程 三、ffmpeg解码&#xff08;照片提取&#xff09; 1.准备工作 &#xff08;1&#xff09;在工程文件夹里面新建三个文件夹 &#xff08;2&#xff09;在main函数中加…

⭐算法OJ⭐跳跃游戏【BFS+滑动窗口】(C++实现)Jump Game 系列 III,VII

⭐算法OJ⭐跳跃游戏【贪心算法】&#xff08;C实现&#xff09;Jump Game 系列 I,II 这篇文章介绍 跳跃游戏 的第三题和第七题&#xff0c;两道题目有异曲同工之妙&#xff0c;都运用了BFS广度优先搜索算法实现&#xff0c;难度相比于前两题较高&#xff0c;而且不同于更常见的…

【QGIS二次开发】地图显示与交互-01

1. 系统界面设计 设计的系统界面如下&#xff0c;很好还原了QGIS、ArcGIS等软件的系统界面&#xff0c;充分利用了QT中顶部工具栏、菜单栏、底部状态栏&#xff0c;实现了图层管理器、鹰眼图、工具箱三个工具面板。 菜单栏、工具栏、工具箱集成了系统中实现的全部功能&#x…

Skynet入门(一)

概念 skynet 是一个为网络游戏服务器设计的轻量框架。但它本身并没有任何为网络游戏业务而特别设计的部分&#xff0c;所以尽可以把它用于其它领域。 设计初衷 如何充分利用它们并行运作数千个相互独立的业务。 模块设计建议 在 skynet 中&#xff0c;用服务 (service) 这…

threejs:用着色器给模型添加光带扫描效果

第一步&#xff1a;给模型添加光带 首先创建一个立方体&#xff0c;不进行任何缩放平移操作&#xff0c;也不要set position。 基础代码如下&#xff1a; 在顶点着色器代码里varying vec3 vPosition;vPosition position;获得threejs自动计算的顶点坐标插值&#xff08;也就…

【时序预测】在线学习:算法选择(从线性模型到深度学习解析)

——如何为动态时序预测匹配最佳增量学习策略&#xff1f; 引言&#xff1a;在线学习的核心价值与挑战 在动态时序预测场景中&#xff08;如实时交通预测、能源消耗监控&#xff09;&#xff0c;数据以流式&#xff08;Streaming&#xff09;形式持续生成&#xff0c;且潜在的…

Spring Boot如何利用Twilio Verify 发送验证码短信?

Twilio提供了一个名为 Twilio Verify 的服务&#xff0c;专门用于处理验证码的发送和验证。这是一个更为简化和安全的解决方案&#xff0c;适合需要用户身份验证的应用。 使用Twilio Verify服务的步骤 以下是如何在Spring Boot中集成Twilio Verify服务的步骤&#xff1a; 1.…

【Linux操作系统】VM17虚拟机安装Ubuntu22.04,图文详细记录

1.双击桌面的 VMware Workstation17 Player&#xff0c;点击“创建新虚拟机”&#xff0c;如下图所示。 2.选择“稍后安装操作系统”&#xff0c;点击“下一步”。如下图所示。 3.客户机操作系统选择“Linux”&#xff0c;版本选择“ Ubuntu 64位”&#xff0c;然后点击“下一…