网关 + Nacos配置管理
网关
网关:就是网络的关口,负责请求的路由、转发、身份校验。
网关路由
- 新建网关模块gateway
- 引入相关依赖
<!--网关-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos discovery-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 写启动类
- 配置路由规则
server:port: 8080 # 前端请求的端口(网关的端口)spring:application:name: gateway # 服务名称cloud:nacos:server-addr: 192.168.140.101:8848 # nacos地址# 路由配置gateway:routes:- id: item-service # 路由规则id,自定义,唯一uri: lb://item-service # 路由目标微服务,lb代表负载均衡协议predicates: # 路由断言,判断请求是否符合要求,符合则路由到目标- Path=/items/**, /search/** # 以请求路径做判断,以/items或/search开头则符合- id: user-serviceuri: lb://user-servicepredicates:- Path=/addresses/**, /users/**- id: trade-serviceuri: lb://trade-servicepredicates:- Path=/orders/**- id: pay-serviceuri: lb://pay-servicepredicates:- Path=/pay-orders/**- id: cart-serviceuri: lb://cart-servicepredicates:- Path=/carts/**
路由属性
网关路由对应的Java类型是RouteDefinition,常见的属性有:
- id:路由唯一标识
- uri:路由目标地址
- predicates:路由断言,判断请求是否符合当前路由
- filters:路由过滤器,对请求或响应做特殊处理
predicates路由断言
文档:predicates路由断言
filters路由过滤器
文档:filters路由过滤器
自定义过滤器
网关过滤器有两种:
- GatewayFilter:路由过滤器,作用于任意指定的路由,默认不生效,要陪知道路由后生效。
- GlobalFilter(常用):全局过滤器,作用范围是所有路由;声明后自动生效。
自定义GlobalFilter
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求HttpHeaders headers = exchange.getRequest().getHeaders();// 过滤器业务处理(登录校验逻辑...)if(...) {// 拦截ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}return chain.filter(exchange); // 放行}// 控制过滤器执行顺序@Overridepublic int getOrder() {return 0; // 值越小,优先级越高}
}
自定义的过滤器需要在NettyRoutingFilter【将请求转发到微服务】这个过滤器之前执行,所以需要再继承一个Ordered接口,来保证我们自定义的过滤器的优先级比NettyRoutingFilter高
网关登录校验
网关传递用户
- 在网关的登录校验过滤器中,从前端发送的请求头里拿到用户信息,并把用户信息放到请求头里,再发给微服务。
ServerWebExchange swe = exchange.mutate().request(builder -> builder.header("user-info", userInfo)).build(); // 传递的时候,需要传递这个返回的新的exchange
- 在微服务中定义拦截器,保存网关发过来的用户信息到ThreadLocal里。
// 定义拦截器
// 因为校验请求头这些操作已经在网关做过了,所以拦截器里边只需要把用户信息保存到ThreadLocal里即可
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取用户信息String userInfo = request.getHeader("user-info");// 判断是否获取了用户信息if(StrUtil.isNotBlank(userInfo)) {// 存入上下文UserContext.setUser(Long.valueOf(userInfo));}// 放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理用户UserContext.removeUser();}
}
// 注册拦截器
/*** DispatcherServlet.class:springmvc的核心api* 防止网关【没有SpringMvc】也引用这个类*/
@ConditionalOnClass(DispatcherServlet.class) // 条件注解
@Configuration
public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor());}
}
由于很多微服务,都需要获取用户信息,不可能在这么多微服务里都一个拦截器,太麻烦啦。所以就把拦截器的代码写在common公共模块。
【问题
】:配置类想要生效,需要被Spring扫描包扫描到,但是现在mvc配置类是在common公共模块下,但是是其他微服务使用这个拦截器,无法扫描到这个配置类。
【解决
】:利用SpringBoot自动装配的原理,将定义的配置类放在了META-INF下的spring.factories文件下,这样就能实现自动装
OpenFeign传递用户信息
【分析
】:购物车服务中的请求,不是直接从网关发过来的,而是网关先发给交易服务,再由交易服务通过OpenFeign向购物车服务中发送请求【微服务之间的调用】。
【解决
】:OpenFeign提供了一个拦截器接口,所有由OpenFeign发起的请求都会先调用拦截器处理请求。
public class DefaultFeignConfig {@Beanpublic RequestInterceptor userInfoRequestInterceptor() {return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate template) {// 交易服务可以拿到用户信息,它向购物车发请求时,UserContext里会保存用户信息Long userId = UserContext.getUser();if (userId != null) {// 把用户信息放到请求头中template.header("user-info", userId.toString()); }}};}
}
Nacos配置管理
【存在问题
】:
- 微服务重复配置过多,维护成本高。
- 业务配置经常变动,每次修改都要重启服务
- 网关路由配置写死,如果变更都要重启网关
配置共享
1. 添加共享配置
打开nacos控制台,添加一些共享配置到nacos中,包括:jdbc、日志、swagger、openfeign等配置。
2. 拉取共享配置
基于NacosConfig拉取共享配置代替微服务的本地配置
- 引入依赖
<!--nacos配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--读取bootstrap文件--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>
2.新建bootstrap.yaml文件
spring:application:name: cart-service # 微服务的名称profiles:active: devcloud:nacos:server-addr: 192.168.140.101:8848config:file-extension: yamlshared-configs:- data-id: shared-jdbc.yaml- data-id: shared-log.yaml- data-id: shared-swagger.yaml
先加载bootstrap配置文件,拉取nacos配置,再进行合并。
配置热更新
当修改配置文件中的配置时,微服务无需重启即可使配置生效。
【条件
】:
- nacos中要有一个与微服务名有关的配置文件。
- 微服务中要以特定方式读取需要热更新的配置属性。
@Data
@Component
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {private Integer maxItems;
}
对应nacos中的配置:
动态路由
要实现动态路由首先要将路由配置保存到nacos中,当nacos中路由配置变更时,推送最新配置到网关,更新网关中的路由信息。
- 拉取配置并添加监听器
- 在
路由表里的内容变更
和项目启动
时,更新路由表
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {private final NacosConfigManager nacosConfigManager;private final RouteDefinitionWriter writer;private final String dataId = "gateway-routes.json";private final String group = "DEFAULT_GROUP";private final Set<String> routeIds = new HashSet<>(); // 保存旧的路由表@PostConstruct // 在项目一启动的时候执行public void init() throws NacosException {// 1. 项目启动,先拉取配置,并添加配置监听器String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(dataId, group, 5000, new Listener() {@Overridepublic Executor getExecutor() { // 定义线程池return null;}@Overridepublic void receiveConfigInfo(String configInfo) { // 配置变更时做的事// 2. 监听到配置变更时,需要去更新路由表updateConfigInfo(configInfo);}});// 3. 第一次读取到配置,也需要更新路由表updateConfigInfo(configInfo);}// 更新路由表【利用RouteDefinitionWriter来更新路由表】public void updateConfigInfo(String configInfo) { // configInfo就是配置文件的内容// 1. 解析配置文件,转为RouteDefinitionList<RouteDefinition> routes = JSONUtil.toList(configInfo, RouteDefinition.class);// 2. 更新路由表// 【删】删除旧的路由表for (String routeId : routeIds) {writer.delete(Mono.just(routeId)).subscribe();}// 清空旧的路由表routeIds.clear();for (RouteDefinition route : routes) {// 【增】新增新的路由表writer.save(Mono.just(route)).subscribe();// 记录路由id,便于下次更新时删除routeIds.add(route.getId());}}
}
- 在nacos中添加动态路由
【注】:为了方便解析从nacos读取到的路由配置,推荐使用json格式的路由配置。
相关文章:

网关 + Nacos配置管理
网关 网关:就是网络的关口,负责请求的路由、转发、身份校验。 网关路由 新建网关模块gateway引入相关依赖 <!--网关--> <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter…...

《Spring Framework实战》6:核心技术 4.1.IoC 容器
欢迎观看《Spring Framework实战》视频教程 本章介绍 Spring 的控制反转 (IoC) 容器。 本部分摘要 Spring IoC 容器和 Bean 简介 容器概述 Bean 概述 依赖 Bean 作用域 自定义 Bean 的性质 Bean 定义继承 容器扩展点 基于注解的容器配置 Clas…...
ModuleNotFoundError: No module named ‘audioop‘
问题 ModuleNotFoundError: No module named pyaudioop ModuleNotFoundError: No module named audioop解决方案 安装库 pip3 install audioop-lts...

STM32-笔记38-I2C-oled实验
一、什么是I2C? I2C总线,全称Inter-Integrated Circuit(互连集成电路),是一种由Philips(现NXP半导体)公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C&…...

人大金仓实现主键自增.
使用数据库中自带的参数类型 serial 类型(相当于创建一个INT列), 或者bigserial(相当于创建一个BIGINT列. 示例sql: CREATE TABLE ord(id SERIAL,ord_no INT NOT NULL,ord_name VARCHAR(32),CONSTRAINT "ord_PKEY" PRIMARY KEY ("id"));插入时指定自增值…...

h264之多视点mvc编码及解码过程(JMVC平台举例)
h264标准参考平台JMVC是针对MVC标准的,JMVC支持多视点编码、合流、多视点解码操作。可以利用JMVC生成h264 mvc码流和解码。 JMVC的下载地址是:jvet / JMVC GitLabH.264/AVC multi-view coding (MVC) extension JMVC reference softwarehttps://vcgit.hh…...

小程序学习08—— 系统参数获取和navBar组件样式动态设置
一 系统信息的概念 uni-app提供了异步(uni.getSystemInfo)和同步(uni.getSystemInfoSync)的2个API获取系统信息。 success 返回参数说明: 参数分类说明statusBarHeight手机状态栏的高度system操作系统名称及版本。。。 二 自定义navbar 2.1 获取系统参数 代码展示…...

数据库环境安装(day1)
网址:MySQL 下载(环境准备): (2-5点击此处,然后选择合适的版本) 1.linux在线YUM仓库 下载/安装: wget https://repo.mysql.com//mysql84-community-release-el9-1.noarch.rpm rpm -i https://r…...

网络安全-web渗透环境搭建-BWAPP(基础篇)
01--所需系统环境: 虚拟主机系统部署(vmware,虚拟主机创建、虚拟主机网络配置(桥接,便于网络中多个主机都能访问虚拟主机)、虚拟软件功能,快照、克隆、镜像文件加载,ova文件制作&am…...

当算法遇到线性代数(三):实对称矩阵
实对称矩阵的理论与应用 线性代数系列相关文章(置顶) 1.当算法遇到线性代数(一):二次型和矩阵正定的意义 2.当算法遇到线性代数(二):矩阵特征值的意义 3.当算法遇到线性代数&#x…...

WayLand的架构和协议
WayLand的架构和协议 1. Wayland简介 1.1 Wayland是啥?为啥它这么重要? 嘿,你知道吗?有时候咱们用电脑的时候,是不是觉得图形界面有点慢、有点卡?那是因为我们还在用一个叫X Window System (X11)的老伙计…...

STM32学习(十)
I2C模块内部结构 I2C(Inter-Integrated Circuit)模块是一种由Philips公司开发的二线式串行总线协议,用于短距离通信,允许多个设备共享相同的总线。 硬件连接简单:I2C通信仅需要两条总线,即SCL&…...

进阶篇-Day17:JAVA的日志、枚举、类加载器、反射等介绍】
目录 1、日志1.1 日志概念1.2 日志框架(1) Logback框架:(2)配置文件介绍: 2、枚举3、类加载器3.1 类加载器的介绍3.2 类加载器的加载过程:加载、链接、初始化3.3 类加载器的分类3.4 双亲委派模式…...

Java设计模式 —— 【行为型模式】责任链模式(Chain-of-responsibility Pattern) 详解
文章目录 模式介绍优缺点适用场景模式结构案例实现 模式介绍 责任链模式又名职责链模式,它是一种对象行为的设计模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链&…...
C++和Python中负数取余结果的区别
C中的负数取余规则(取模%)规则 在C中,取余运算( % )的结果符号与被除数相同。从数学定义角度看,C遵循的是尽量让商向零取整的规则。例如计算 -7/3,商是 -2 (向零取整)&a…...

rust学习——环境搭建
rust安装:https://kaisery.github.io/trpl-zh-cn/ch01-01-installation.html 1、vscode装插件: toml语法支持 依赖管理 rust语法支持 2、创建demo 3、查看目录 4、执行文件的几种方式: rust安装:https://www.rust-lang.org/z…...

Linux系统中解决端口占用问题
在日常的 Linux 系统管理和开发过程中,端口占用是一个常见且令人头疼的问题。无论是部署新服务、调试应用程序,还是进行系统维护,遇到端口被占用都可能导致服务无法正常启动或运行。本文将详细介绍在 Linux 系统中如何识别和解决端口占用问题…...
现代软件架构设计:14个质量属性的定义、权衡与最佳实践
1. 引言 1.1 技术架构的重要性 技术架构是指导软件系统设计和开发的核心,它定义了系统的高层结构及关键技术选型。一个优秀的技术架构可以提高开发效率、系统稳定性和扩展能力,确保项目成功落地。面对复杂业务场景,技术架构的设计至关重要&…...

【UE5 C++课程系列笔记】25——多线程基础——FGraphEventRef的简单使用
目录 概念 使用示例1 使用示例2 概念 FGraphEventRef 本质上是对一个异步任务或者一组相关异步任务在虚幻引擎任务图系统中的一种引用(reference)。虚幻引擎的任务图系统用于高效地调度和管理各种异步任务,协调它们的执行顺序以及处理任务…...
计算机网络之---信号与编码
信号 在物理层,信号是用来传输比特流的物理量,它可以是电压、电流、光强度等形式,通常通过电缆、光纤或者无线信道等媒介传播。 信号主要分为以下两种类型: 模拟信号(Analog Signal):信号在时间…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...