JAVA开发(Spring Gateway 的原理和使用)
在springCloud的架构中,业务服务都是以微服务来划分的,每个服务可能都有自己的地址和端口。如果前端或者说是客户端直接去调用不同的微服务的话,就要配置不同的地址。其实这是一个解耦和去中心化出现的弊端。所以springCloud体系中,又将这一层的调用封装一层,使一切调用都经过网关,前端和客户端只需要和网关交互,而不需要关注每个微服务的地址,只需要知道微服务的名称就可以。当微服务的地址改变时,只需要修改网关就可以,前端和客户端不需要任何修改,这也方便了服务的扩容和分布式部署。这里的网关就是相当于一个队长的作用。外部的东西一切找队长,团队里自己的事情由队长和成员内部解决。

spring gateway的作用有点像封装了post和get的请求过程,增加不同微服务的路由断言判断访问哪个微服务,这里的微服务需要注册中心的协助,网关主要去找注册中心里注册的服务;
客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行 post 过滤器逻辑。
其原理架构如下:


Gateway 接收客户端请求。客户端请求与路由信息进行匹配,匹配成功的才能够被发往相应的下游服务。请求经过 Filter 过滤器链,执行 pre 处理逻辑,如修改请求头信息等。请求被转发至下游服务并返回响应。响应经过 Filter 过滤器链,执行 post 处理逻辑。向客户端响应应答。

API 网关也存在不足之处,在微服务这种去中心化的架构中,网关又成了一个中心点,它增加了一个我们必须开发、部署和维护的高可用组件。正是由于这个原因,在网关设计时必须考虑即使 API 网关宕机也不要影响到服务的调用和运行,所以需要对网关的响应结果有数据缓存能力,通过返回缓存数据或默认数据屏蔽后端服务的失败。
主要网关对比选型:

网关的作用:
性能:API高可用,负载均衡,容错机制。
安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
限流:流量控制,错峰流控,可以定义多种限流规则。
缓存:数据缓存。
日志:日志记录,一旦涉及分布式,全链路跟踪必不可少。
监控:记录请求响应数据,api耗时分析,性能监控。

网关的使用,配置
pom文件:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>3.0.7</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><exclusions><exclusion><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>${xstream.version}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency><dependency><groupId>com.ctrip.framework.apollo</groupId><artifactId>apollo-client</artifactId><version>1.8.0</version><scope>compile</scope></dependency><!-- 健康检查 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId><version>2.6.3</version></dependency>
yml文件配置详解:
#应用ID
app:id: cn-maoheyeren-plat#端口
server:port: 8300#应用版本
deploy:version: -v1#服务名称
spring:application:name: base-gatewaycloud:gateway:discovery:locator:enabled: false # 这个配置是默认给每个服务创建一个router,设置为false防止请求默认转发到url中包含的微服务名上#例:/auth/**会默认转发到服务auth下,而不是转发到配置的urilower-case-service-id: true # 微服务名称以小写形式呈现routes:- id: base-admin #微服务路由规则uri: lb://base-admin #负载均衡,将请求转发到注册中心的base-adminpredicates: #断言,如果前端请求包含/base-admin/,则走这条规则- Path=/base-admin/**filters: # 过滤器 /base-admin/** 转发到 uri/**- StripPrefix=1- id: maoheyeren-businessuri: lb://maoheyeren-businesspredicates:- Path=/maoheyeren-business/**filters: # /maoheyeren-business/** 转发到 uri/**- StripPrefix=1- id: maoheyeren-cockpituri: lb://maoheyeren-cockpitpredicates:- Path=/maoheyeren-cockpit/**filters: # /maoheyeren-cockpit/** 转发到 uri/**- StripPrefix=1- id: maoheyeren-datauri: lb://maoheyeren-datapredicates:- Path=/maoheyeren-data/**filters: # /maoheyeren-data/** 转发到 uri/**- StripPrefix=1
网关中过滤器的编写使用:
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;@Slf4j
@Component
public class PermissionGatewayFilter implements GatewayFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("执行了自定义的全局过滤器");//1.获取请求参数access-tokenString token = exchange.getRequest().getQueryParams().getFirst("access-token");//2.判断是否存在if(token == null) {//3.如果不存在 : 认证失败log.info("没有获取到token");exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete(); //请求结束}//4.如果存在,继续执行return chain.filter(exchange); //继续向下执行}@Overridepublic int getOrder() {return 0;}}
spring gateway 实现限流
/*** 自定义过滤器*/
@Component
@Slf4j
@Order(-1)
public class RequestRateLimitFilter implements GlobalFilter {private static final Cache<String, RateLimiter> RATE_LIMITER_CACHE = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(1, TimeUnit.HOURS).build();private static final double DEFAULT_PERMITS_PER_SECOND = 1; // 令牌桶每秒填充速率@SneakyThrows@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String remoteAddr = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();RateLimiter rateLimiter = RATE_LIMITER_CACHE.get(remoteAddr, () -> RateLimiter.create(DEFAULT_PERMITS_PER_SECOND));if (rateLimiter.tryAcquire()) {return chain.filter(exchange);}ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");DataBuffer dataBuffer = response.bufferFactory().wrap("Too Many Request!!!".getBytes(StandardCharsets.UTF_8));return response.writeWith(Mono.just(dataBuffer));}
}
/*** 自定义局部限流**/
@Component
public class CustomRequestRateLimitGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomRequestRateLimitGatewayFilterFactory.Config> {public CustomRequestRateLimitGatewayFilterFactory() {super(Config.class);}private static final Cache<String, RateLimiter> RATE_LIMITER_CACHE = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(1, TimeUnit.HOURS).build();@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@SneakyThrows@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String remoteAddr = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();RateLimiter rateLimiter = RATE_LIMITER_CACHE.get(remoteAddr, () ->RateLimiter.create(Double.parseDouble(config.getPermitsPerSecond())));if (rateLimiter.tryAcquire()) {return chain.filter(exchange);}ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");DataBuffer dataBuffer = response.bufferFactory().wrap("Too Many Request!!!".getBytes(StandardCharsets.UTF_8));return response.writeWith(Mono.just(dataBuffer));}};}@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("permitsPerSecond");}@Datapublic static class Config {private String permitsPerSecond; // 令牌桶每秒填充速率}
}
相关文章:
JAVA开发(Spring Gateway 的原理和使用)
在springCloud的架构中,业务服务都是以微服务来划分的,每个服务可能都有自己的地址和端口。如果前端或者说是客户端直接去调用不同的微服务的话,就要配置不同的地址。其实这是一个解耦和去中心化出现的弊端。所以springCloud体系中࿰…...
踩坑:解决npm版本升级报错,无法安装node-sass的问题
npm版本由于经常更新,迁移前端项目时经常发现报错安装不上。 比如,项目经常使用的sass模块,可能迁移的时候就发现安装不了。 因为node-sass 编译器是通过 C 实现的。在 Node.js 中,采用 gyp 构建工具进行构建 C 代码,…...
xFormers安装使用
xFormers是一个模块化和可编程的Transformer建模库,可以加速图像的生成。 这种优化仅适用于nvidia gpus,它加快了图像生成,并降低了vram的使用量,而成本产生了非确定性的结果。 下载地址: https://github.com/faceb…...
React—— hooks(一)
🧁个人主页:个人主页 ✌支持我 :点赞👍收藏🌼关注🧡 文章目录⛳React Hooks💸useState(保存组件状态)🥈useEffect(处理副作用)🔋useCallback(记忆函数&#…...
Ubuntu20.04下noetic版本ros安装时rosdep update失败解决方法【一行命令】
一、问题: 安装完ros后,需要执行sudo rosdep init,但是在没有全局科学上网的前提下,执行sudo rosdep init势必会报错: ERROR: cannot download default sources list from: https://raw.githubusercontent.com/ros/r…...
Vue2.0开发之——购物车案例-Footer组件封装-计算商品的总价格(51)
一 概述 App.vue中计算勾选商品的总价格定义子组件Footer中的商品总价格将App.vue中商品的总价格传递给Footer显示 二 App.vue中计算勾选商品的总价格 2.1 商品总价格的计算逻辑 所有勾选商品的价格*数量 2.2 App.vue中通过计算属性计算总价格 通过计算属性计算总价格 co…...
德鲁特金属导电理论(Drude)
德鲁特模型的重要等式 首先我们建立德鲁特模型的重要等式 我们把原子对于电子的阻碍作用,用一个冲量近似表示出来 在式子 首先定义一个等效加速度 由于 我们可以得到电导率的微观表达式 在交流电环境中 电场的表达式 借鉴上一问的公式 我们可以列出这样的表达式…...
(十一)python网络爬虫(理论+实战)——html解析库:BeautfulSoup详解
系列文章: python网络爬虫专栏 目录 序言 本节学习目标 特别申明...
四轮两驱小车(五):蓝牙HC-08通信
前言: 在我没接触蓝牙之前,我觉得蓝牙模块应用起来应该挺麻烦,后来发觉这个蓝牙模块的应用本质无非就是一个串口 蓝牙模块: 这是我从某宝上买到的蓝牙模块HC-08,价格还算可以,而且可以适用于大多数蓝牙调试…...
华为OD机试题 - 对称美学(JavaScript)| 机考必刷
华为OD机试题 最近更新的博客使用说明本篇题解:对称美学题目输入输出示例一输入输出说明示例二输入输出备注Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典...
Web Spider案例 网洛克 第四题 JSFuck加密 练习(八)
声明 此次案例只为学习交流使用,抓包内容、敏感网址、数据接口均已做脱敏处理,切勿用于其他非法用途; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 JSFuck解决方式…...
【JavaScript速成之路】JavaScript数组
📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言1,初识数组1.1,数组1.2,创建数组1.3&…...
路由传参含对象数据刷新页面数据丢失
目录 一、问题描述 二、 解决办法 一、问题描述 【1】众所周知,在veu项目开发过程中,我们常常会用到通过路由的方式在页面中传递数据。但是用到this.$route.query.ObjectData的页面,刷新后会导致this.$route.query.ObjectData数据丢失。 …...
大数据flink框架入门分享(起源与发展、实时与离线计算、场景、处理流程、相关概念、特性普及、入门Demo)
文章目录起源与发展flink在github上的现状实时计算VS离线计算实时计算离线计算实时计算常用的场景框架流处理流程flink电商场景下的业务图示例flink中一些重要特性有界数据和无界数据时间语义、水位线事件时间处理时间水位线flink窗口概念理想中的数据处理含有延迟数据的数据处…...
由点到面贯穿整个Java泛型理解
泛型概述 Java泛型(generics)是DK5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。 泛型的本质就是参数化类型,也就是所操作的数据类型被指定为一个参数。 如我们经常使用的Array…...
北斗RTK高精度定位在AI领域的应用
随着北斗高精度定位技术越来越成熟,通过GNSS高精度定位与机器人结合,越来越多的智能机器人走进我们生活中。像驾培机器人、智能除草机器人、智能巡检机器人、北斗划线机器人等智能机器人已经广泛的投入使用。驾培机器人驾培机器人:通考车安装…...
2023年再不会 IOC 源码,就要被淘汰了
👏作者简介:大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,CSDN博客专家,阿里云专家博主📕系列专栏:Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…...
MQ面试题
1、为什么使用消息队列? 其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息队列是什么? 面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景&…...
pnpm 基本详细使用(安装、卸载、使用)
一、简介 官网地址、GitHub地址、官方安装文档、官方卸载文档。 pnpm 全称 performant npm,意思为 高性能的 npm。pnpm 由 npm/yarn 衍生而来,解决了 npm/yarn 内部潜在的 bug,极大的优化了性能,扩展了使用场景。被誉为 最先进的…...
Kafka生产者的粘性分区算法
分区算法分类 kafka在生产者投递消息时,会根据是否有key采取不用策略来获取分区。 存在key时会根据key计算一个hash值,然后采用hash%分区数的方式获取对应的分区。 而不存在key时采用随机算法选取分区,然后将所有的消息封装到这个batch上直…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
