网关 + 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):信号在时间…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...