Gateway 统一网关

一、初识 Gateway

1. 为什么需要网关

我们所有的服务可以让任何请求访问,但有些业务不是对外公开的,这就需要用网关来统一替我们筛选请求,它就像是房间的一道门,想进入房间就必须经过门。而请求想要访问微服务,就必须通过网关再到微服务。

2. 网关的作用

  • 身份认证和权限校验

网关是微服务的入口,会验证用户是否有请求资格,如果没有则进行拦截

  • 服务路由、负载均衡

网关不处理业务,根据拟定好的规则,将请求转发到对应的微服务中,这个过程就是路由。当对应的微服务有部署了多个,同样需要根据拟定的规则做负载均衡。

  • 请求限流

请求量过高时,网关根据微服务能够接受的请求量来放行请求,避免服务压力过大。就像是红绿灯避免交通堵塞的原理类似。

在 SprignCloud 中网关的实现包括两种:

  • gateway
  • zuul:zuul 是基于 Servlet 实现的,属于阻塞式编程。而SpringCloudGateway 是基于 Spring5 中提供的 WebFlux, 属于响应式编程的实现,具备更好的性能。

二、入门案例

1. 创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖,如果没有统一管理版本号,需要加上<version></version>

<!--nacos服务注册发现依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--网关gateway依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>

2.  编写启动类

@SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}

3. 路由配置及nacos地址

3.1 创建application.yml文件

server:port: 10010 # 网关端口
spring:application:name: gateway # 服务名称cloud:nacos:server-addr: localhost:8848 # nacos地址gateway:routes: # 网关路由配置(routes: 多个; route: 一个)- id: user-service # 路由id,自定义,只要唯一即可uri: lb://userservice # 第一种写法:路由的目标地址; lb(loadBalance)是指负载均衡,后面跟服务名称predicates: # 路由断言,也就是判断请求是否符合路由规则的条件(断言一般是布尔类型)- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
#        可以同时配置多个服务路由- id: baidu-demouri: https://www.baidu.com  # 第二种写法:路由的目标地址 http就是固定地址predicates:- Path=/baidu/** # 注意使用本服务测试需要开启下面截取path,不然拼接的路径无效
#         filters: 
# path断言路由的请求格式默认为uri+path,如果不需要携带path可以截取掉
#           - StripPrefix=1    # 截取掉- Path中的第一级路径/baidu# 初学期间为了方便调试与快速定位错误,可以将gateway打印日志级别调低
logging:level:org:springframework:cloud:gateway: trace

路由的配置包括:

1.路由id:路由的唯一标示

2.路由目标(uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡

3.路由断言(predicates):判断路由的规则,一般是布尔类型

4.路由过滤器(filters):对请求或响应做处理

重启网关服务, 访问 localhost:10010/user/1,如下图所示 

被拦截状态

至此案例到此结束,为了更好的了解网关在这期间默默的付出了哪些,下面将网关原理聊一聊。

用户发送请求后,首先会通过网关,而网关是不做任何业务的,会去注册中心 Nacos 中拉取服务列表,然后根据负载均衡选择一个服务发送用户的请求。如下图

三、断言工厂

我们配置文件中写的断言规则是字符串,这些字符串会被断言工厂(Route Predicate Factory读取处理,转变为路由判断的条件。断言工厂为我们把字符串转变为了判断条件。例如 Path=/user/** 是按照路径匹配,这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的。像这样的断言工厂在SpringCloudGateway还有十几个。

名称说明示例
After是某个时间点后的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before是某个时间点之前的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between是某两个时间点之前的请求- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie请求必须包含某些cookie- Cookie=chocolate, ch.p
Header请求必须包含某些header- Header=X-Request-Id, \d+
Host请求必须是访问某个host(域名)- Host=.somehost.org,.anotherhost.org
Method请求方式必须是指定方式- Method=GET,POST
Path请求路径必须符合指定规则- Path=/red/{segment},/blue/**
Query请求参数必须包含指定参数- Query=name, Jack或者- Query=name
RemoteAddr请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24
Weight权重处理

四、过滤器工厂

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理

Spring提供了31种不同的路由过滤器工厂。例如:

名称说明
AddRequestHeader给当前请求添加一个请求头
RemoveRequestHeader移除请求中的一个请求头
AddResponseHeader给响应结果中添加一个响应头
RemoveResponseHeader从响应结果中移除有一个响应头
RequestRateLimiter限制请求的流量
……

下面举个例子给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!

实现方式:

1.  局部过滤器(GatewayFilter)

filters : 配置在路由下的过滤器只对当前路由的请求生效, filters 在 routes 的目录下

1. 在gateway中修改application.yml文件, 给userservice的路由添加过滤器

spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path=/user/** filters: # 路由过滤器- AddRequestHeader=Truth, me is freaking awesome! # 添加请求头

为了方便观察是否添加成功,这里改造方法如下 

2.  默认过滤器(DefaultFilter)

default-filters  : 对所有路由都生效的过滤器,  default-filters 和 routes 同级目录

spring:cloud:gateway:routes:- id: user-service uri: lb://userservice predicates: - Path=/user/**default-filters: # 默认过滤器- AddRequestHeader=Truth, me is freaking awesome! 

3. 全局过滤器(GlobalFilter)

全局过滤器 (GlobalFilter) 的作用也是处理一切进入网关的请求和微服务响应,与上面的作用一样。

区别在于

  • GatewayFilter通过配置定义,处理逻辑是固定的。
  • 上面的逻辑需要自己写代码实现,定义方式是实现GlobalFilter接口。
public interface GlobalFilter {/***  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理** @param exchange 请求上下文,里面可以获取Request、Response等信息* @param chain 用来把请求委托给下一个过滤器 * @return {@code Mono<Void>} 返回标示当前过滤器业务结束*/Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

3.1 自定义全局过滤器

需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

参数中是否有authorization?authorization参数值是否为admin?如果同时满足则放行,否则拦截

实现步骤

1. 在 gateway 中定义一个过滤器

@Order(-1)  // 权重注解,值越小优先级越高
@Component
public class AuthorizeFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取请求参数MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();// 2.获取authorization参数String auth = params.getFirst("authorization");// 3.校验if ("admin".equals(auth)) {// 放行return chain.filter(exchange);}// 4.拦截// 4.1.禁止访问,设置状态码exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);// 4.2.结束处理return exchange.getResponse().setComplete();}
}

2. 测试,访问 http://localhost:10010/user/1?authorization=admin 可以看到成功获取到响应结果

若不符合要求则无法获取结果

4. 过滤器的执行顺序

请求进入网关会碰到三类过滤器,当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将当前路由过滤器和 DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器。

过滤器执行顺序

  1. 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
  2. GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order,由我们自己指定。
  3. 路由过滤器和defaultFilterorderSpring指定,默认是按照声明顺序1递增
  4. 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

 4.1 定义执行顺序的两种方式

5. 限流过滤器

限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。限流算法如下:

  • 计数器算法,又包括固定窗口计数器算法、滑动窗口计数器算法
  • 漏桶算法(Leaky Bucket)
  • 令牌桶算法(Token Bucket

1. 计数器算法 --- 固定窗口计数器算法

  • 将时间划分为多个窗口;
  • 在每个窗口内每有一次请求就将计数器加一,当时间到达下一个窗口时,计数器重置。
  • 如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃。

 但是这种会有个问题,假如我们在1s内允许通过的请求数量是100,如果在窗口失效的最后几毫秒发送了99个请求,接着又在下一个时间窗口开始时发送99个请求,那么这个用户这1s内就不止发送100个请求了,这就是临界值问题。

 

2. 计数器算法 --- 滑动窗口计数器算法

滑动窗口计算算法就是为了解决固定窗口计算算法存在临界值的问题而出现的。假设我们1秒内允许通过100个请求,但我们把1秒分成多个窗格(窗格数越多,流量过度越平滑)。

3. 漏桶算法

  • 将每个请求视作"水滴"放入"漏桶"进行存储;
  • "漏桶"以固定速率向外""出请求来执行,如果"漏桶"空了则停止"漏水”;
  • 如果"漏桶"满了则多余的"水滴"会被直接丢弃。

 

4. 令牌桶算法 

以固定的速率生成令牌,存入令牌桶中,如果令牌桶满了以后,多余令牌丢弃

六、跨域问题

  • 跨域:域名、端口、协议三者任意一个不同就是跨域

域名不同: www.taobao.com www.taobao.org www.jd.commiaosha.jd.com

端口不同:localhost:8080和localhost:8081

协议不同:https:xxx.com 和 http:xxx.com

  • 跨域问题:浏览器禁止请求发送者与服务端跨域ajax请求,说白了就是请求被浏览器拦截的问题
  • 解决方案:CORS (跨域资源共享)

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:

spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题corsConfigurations:'[/**]':allowedOrigins: # 允许哪些网站的跨域请求 - "http://localhost:8090"allowedMethods: # 允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期, 有效期内浏览器不询问是否拦截

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/459583.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32主从定时器输出个数、频率可调的脉冲

STM32中发出脉冲一般有两种方式&#xff1a; 1&#xff09;利用定时中断输出脉冲&#xff0c;但是间隔的延时会影响其他主程序的进程&#xff0c;当控制多个电机的时候就非常不可取&#xff1b; 2&#xff09;利用PWM脉宽调制&#xff0c;并通过主从定时器进行设定&#xff0…

微知-Lecroy力科的PCIe协议分析仪型号命名规则(PCIe代,金手指lanes数量)

文章目录 要点主要型号命名规则各代主要产品图片Summit M616 协议分析仪/训练器Summit T516 分析仪Summit T416 分析仪Summit T3-16分析仪Summit T28 分析仪 综述 要点 LeCroy(力科)成立于1964年&#xff0c;是一家专业生产示波器厂家。在美国纽约。一直把重点放在研制改善生产…

安卓14上蓝牙调用SystemProperties.set(),解决找不到SystemProperties.set()的问题

近期遇到一个需求&#xff0c;要在安卓14的蓝牙模块中调用SystemProperties.set()。 安卓14中的蓝牙&#xff0c;和安卓12的版本有较大的不同。它在packages/modules目录下&#xff0c;而安卓12是分散在packages/apps和frameworks/base等目录下&#xff1b;安卓14的蓝牙打包产…

Hash表算法

哈希表 理论知识&#xff08;本文来自于代码随想录摘抄&#xff09;什么是哈希常见的三种哈希结数组&#xff1a;set:map:其他常用方法或者技巧&#xff08;自己总结的&#xff09; 练习题和讲解有效的字母移位词349. 两个数组的交集1. 两数之和454. 四数相加 II15. 三数之和 总…

4款专业音频在线剪辑工具帮你开启创意之路。

音频在线剪辑工具能够为我们提供很大的便利&#xff0c;对于不管是专业的音乐制作人还是音频创作爱好者来说&#xff0c;都能借助一些音频编辑工具来充分发挥自己的创意。所以这一次&#xff0c;我要给大家介绍几个专业方便的音频剪辑工具。 1、福昕音频在线 直达链接&#x…

基于yolov8的布匹缺陷检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于yolov8的布匹缺陷检测系统&#xff0c;支持图像、视频和摄像实时检测【pytorch框架、python源码】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov8的布匹缺陷检测系统是在 PyTo…

基于SSM的心理咨询管理管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的心理咨询管理管理系统拥有三个角色&#xff1a;学生用户、咨询师、管理员 管理员&#xff1a;学生管理、咨询师管理、文档信息管理、预约信息管理、测试题目管理、测试信息管理…

Cesium基础-(Entity)-(Corridor 走廊)

里边包含Vue、React框架代码详细步骤、以及代码详细解释 4、Corridor 走廊 以下是 CorridorGeometry 类的属性、方法和静态方法,以表格形式展示: 属性 属性名类型默认值描述positionsArray.定义走廊中心的坐标点数组。widthnumber走廊

预览 PDF 文档

引言 在现代Web应用中&#xff0c;文件预览功能是非常常见的需求之一。特别是在企业级应用中&#xff0c;用户经常需要查看各种类型的文件&#xff0c;如 PDF、Word、Excel 等。本文将详细介绍如何在Vue项目中实现 PDF 文档的预览功能。 实现原理 后端API 后端需要提供一个…

GIT使用list

清空当前commit区 方法 1&#xff1a;软重置到初始状态 如果希望保留文件内容&#xff0c;但清空所有 commit 历史&#xff0c;可以使用以下命令&#xff1a; git reset --soft $(git rev-list --max-parents0 HEAD)解释&#xff1a; --soft 表示重置 commit 历史&#xff…

uniapp的IOS证书申请(测试和正式环境)及UDID配置流程

1.说明 本教程只提供uniapp在ios端的证书文件申请&#xff08;包含正式环境和开发环境&#xff09;、UDID配置说明&#xff0c;请勿用文档中的账号和其他隐私数据进行测试&#xff0c;请勿侵权&#xff01; 2.申请前准备 证书生成网站&#xff1a;苹果应用上传、解析&#x…

【AscendC算子开发】笔记3 矩阵计算及高级开发技巧

pytorch调用算子 矩阵计算 为什么上图提供了两种矩阵结果访问方式&#xff1f; 如果只需要结果&#xff0c;那么拿注释的一行代码就可以得到结果&#xff0c;如果之后还有其他的操作&#xff0c;可以计算一小块就用起来&#xff0c;那么需要使用上述操作&#xff0c;可以形成流…

Unity Newtonsoft.Json 大对象序列化失败

Unity Newtonsoft.Json 大对象序列化失败 &#x1f4a3;崩溃了没&#xff1f;&#x1f600;替代方案 &#x1f4a3;崩溃了没&#xff1f; Newtonsoft.Json.JsonTextWriter:WriteValueInternal(string,Newtonsoft.Json.JsonToken) InvalidCastException: Specified cast is not…

Kafka认证时Successfully logged in真的认证成功了?

背景 某个应用需要配置 Kafka 集群信息&#xff0c;且需要在验证集群是否可达。基本实现思路是创建一个生产者对象&#xff0c;然后发送一条测试数据&#xff0c;调用 Producer 的 send 方法发送消息后&#xff0c;再调用 get() 方法&#xff0c;即同步发送消息&#xff0c;测…

SpringBoot后端开发常用工具详细介绍——flyway数据库版本控制工具

文章目录 什么是flyway简介为什么要使用flyway 流程介绍整合springboot添加pom文件配置flyway向resource/db/migration添加sql文件 注意事项1. 迁移报错2. 迁移顺序 参考 什么是flyway 简介 为什么要使用flyway 我们在开发时往往会有这样一种情况&#xff1a; 进行软件开发…

【Linux系统编程】线程深入运用

目录 一&#xff0c;C线程与系统线程 二&#xff0c;分离线程 三&#xff0c;线程结构 四&#xff0c;__thread关键字 五&#xff0c;Linux线程互斥 1&#xff0c;线程互斥相关的背景概念 2&#xff0c;互斥锁 3&#xff0c;死锁 4&#xff0c;互斥锁的弊端 六&#…

2024年10月25日练习(双指针算法)

一.283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 1.题目描述&#xff1a; 这里题目要求了说必须在不复制数组的情况下对数组进行原地操作&#xff0c;所以说不能来用暴力的解法来 实现。 2.算法原理&#xff1a; 这个题目就是经典的数组划分&#xff0c;数组分块问题…

react-signature-canvas 实现画笔与橡皮擦功能

react-signature-canvas git 地址 代码示例 import React, { Component } from react import { createRoot } from react-dom/clientimport SignaturePad from ../../src/index.tsximport * as styles from ./styles.module.cssclass App extends Component {state { trimmed…

NLTK无法下载?

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 nltk无法下载怎么办&#xff1f;什么是NLTK&#xff1f;为什么要用NLTK&#xff1f;如何下载&#xff1f; nltk无法下载怎么办&#xff1f; 什么是NLTK&#xff1f; NLTK是学习自然…

【Qt】窗口——Qt窗口的概念、常用的窗口函数、菜单栏、工具栏、状态栏、浮动窗口、对话框

文章目录 Qt窗口Qt窗口的概念菜单栏工具栏状态栏浮动窗口对话框 Qt 窗口 Qt窗口的概念 QMainWindow 类概述&#xff1a; QMainWindow 是一个为用户提供主窗口程序的类&#xff0c;它继承自 QWidget 类&#xff0c;并且提供了一个预定义的布局。 菜单栏 菜单栏常用属性&#xf…