当前位置: 首页 > news >正文

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的架构中&#xff0c;业务服务都是以微服务来划分的&#xff0c;每个服务可能都有自己的地址和端口。如果前端或者说是客户端直接去调用不同的微服务的话&#xff0c;就要配置不同的地址。其实这是一个解耦和去中心化出现的弊端。所以springCloud体系中&#xff0…...

踩坑:解决npm版本升级报错,无法安装node-sass的问题

npm版本由于经常更新&#xff0c;迁移前端项目时经常发现报错安装不上。 比如&#xff0c;项目经常使用的sass模块&#xff0c;可能迁移的时候就发现安装不了。 因为node-sass 编译器是通过 C 实现的。在 Node.js 中&#xff0c;采用 gyp 构建工具进行构建 C 代码&#xff0c…...

xFormers安装使用

xFormers是一个模块化和可编程的Transformer建模库&#xff0c;可以加速图像的生成。 这种优化仅适用于nvidia gpus&#xff0c;它加快了图像生成&#xff0c;并降低了vram的使用量&#xff0c;而成本产生了非确定性的结果。 下载地址&#xff1a; https://github.com/faceb…...

React—— hooks(一)

&#x1f9c1;个人主页&#xff1a;个人主页 ✌支持我 &#xff1a;点赞&#x1f44d;收藏&#x1f33c;关注&#x1f9e1; 文章目录⛳React Hooks&#x1f4b8;useState(保存组件状态)&#x1f948;useEffect(处理副作用)&#x1f50b;useCallback&#xff08;记忆函数&#…...

Ubuntu20.04下noetic版本ros安装时rosdep update失败解决方法【一行命令】

一、问题&#xff1a; 安装完ros后&#xff0c;需要执行sudo rosdep init&#xff0c;但是在没有全局科学上网的前提下&#xff0c;执行sudo rosdep init势必会报错&#xff1a; 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)

德鲁特模型的重要等式 首先我们建立德鲁特模型的重要等式 我们把原子对于电子的阻碍作用&#xff0c;用一个冲量近似表示出来 在式子 首先定义一个等效加速度 由于 我们可以得到电导率的微观表达式 在交流电环境中 电场的表达式 借鉴上一问的公式 我们可以列出这样的表达式…...

(十一)python网络爬虫(理论+实战)——html解析库:BeautfulSoup详解

系列文章: python网络爬虫专栏 目录 序言 本节学习目标 特别申明...

四轮两驱小车(五):蓝牙HC-08通信

前言&#xff1a; 在我没接触蓝牙之前&#xff0c;我觉得蓝牙模块应用起来应该挺麻烦&#xff0c;后来发觉这个蓝牙模块的应用本质无非就是一个串口 蓝牙模块&#xff1a; 这是我从某宝上买到的蓝牙模块HC-08&#xff0c;价格还算可以&#xff0c;而且可以适用于大多数蓝牙调试…...

华为OD机试题 - 对称美学(JavaScript)| 机考必刷

华为OD机试题 最近更新的博客使用说明本篇题解:对称美学题目输入输出示例一输入输出说明示例二输入输出备注Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典...

Web Spider案例 网洛克 第四题 JSFuck加密 练习(八)

声明 此次案例只为学习交流使用&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;切勿用于其他非法用途&#xff1b; 文章目录声明一、资源推荐二、逆向目标三、抓包分析 & 下断分析逆向3.1 抓包分析3.2 下断分析逆向拿到混淆JS代码3.3 JSFuck解决方式…...

【JavaScript速成之路】JavaScript数组

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;初识数组1.1&#xff0c;数组1.2&#xff0c;创建数组1.3&…...

路由传参含对象数据刷新页面数据丢失

目录 一、问题描述 二、 解决办法 一、问题描述 【1】众所周知&#xff0c;在veu项目开发过程中&#xff0c;我们常常会用到通过路由的方式在页面中传递数据。但是用到this.$route.query.ObjectData的页面&#xff0c;刷新后会导致this.$route.query.ObjectData数据丢失。 …...

大数据flink框架入门分享(起源与发展、实时与离线计算、场景、处理流程、相关概念、特性普及、入门Demo)

文章目录起源与发展flink在github上的现状实时计算VS离线计算实时计算离线计算实时计算常用的场景框架流处理流程flink电商场景下的业务图示例flink中一些重要特性有界数据和无界数据时间语义、水位线事件时间处理时间水位线flink窗口概念理想中的数据处理含有延迟数据的数据处…...

由点到面贯穿整个Java泛型理解

泛型概述 Java泛型(generics)是DK5中引入的一个新特性&#xff0c;泛型提供了编译时类型安全监测机制&#xff0c;该机制允许我们在编译时检测到非法的类型数据结构。 泛型的本质就是参数化类型&#xff0c;也就是所操作的数据类型被指定为一个参数。 如我们经常使用的Array…...

北斗RTK高精度定位在AI领域的应用

随着北斗高精度定位技术越来越成熟&#xff0c;通过GNSS高精度定位与机器人结合&#xff0c;越来越多的智能机器人走进我们生活中。像驾培机器人、智能除草机器人、智能巡检机器人、北斗划线机器人等智能机器人已经广泛的投入使用。驾培机器人驾培机器人&#xff1a;通考车安装…...

2023年再不会 IOC 源码,就要被淘汰了

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…...

MQ面试题

1、为什么使用消息队列&#xff1f; 其实就是问问你消息队列都有哪些使用场景&#xff0c;然后你项目里具体是什么场景&#xff0c;说说你在这个场景里用消息队列是什么&#xff1f; 面试官问你这个问题&#xff0c;期望的一个回答是说&#xff0c;你们公司有个什么业务场景&…...

pnpm 基本详细使用(安装、卸载、使用)

一、简介 官网地址、GitHub地址、官方安装文档、官方卸载文档。 pnpm 全称 performant npm&#xff0c;意思为 高性能的 npm。pnpm 由 npm/yarn 衍生而来&#xff0c;解决了 npm/yarn 内部潜在的 bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景。被誉为 最先进的…...

Kafka生产者的粘性分区算法

分区算法分类 kafka在生产者投递消息时&#xff0c;会根据是否有key采取不用策略来获取分区。 存在key时会根据key计算一个hash值&#xff0c;然后采用hash%分区数的方式获取对应的分区。 而不存在key时采用随机算法选取分区&#xff0c;然后将所有的消息封装到这个batch上直…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...