当前位置: 首页 > 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上直…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...