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

什么是网关路由

1.认识网关

网关(Gateway)和路由(Router)是两个相关但不同的概念。

一、网关(Gateway)

  1. 定义
    • 网关是一个网络节点,它充当了不同网络之间的连接点。可以将其看作是一个网络的 “大门”,用于在不同的网络(如本地网络和外部互联网、两个不同的局域网等)之间传递数据。
    • 例如,在一个企业内部网络连接到互联网时,防火墙设备通常就充当网关。它接收来自内部网络的请求,将这些请求转发到互联网,并将互联网返回的数据再转发回内部网络。
  2. 功能
    • 协议转换:不同的网络可能使用不同的网络协议。网关能够在这些不同协议之间进行转换。比如,内部网络可能使用 IPX/SPX 协议,而外部网络使用 TCP/IP 协议,网关可以把基于 IPX/SPX 协议的数据包转换为 TCP/IP 协议的数据包,反之亦然。
    • 数据转发:网关会根据数据包的目的地址决定数据的流向。当它收到一个数据包时,会查看数据包的目标网络地址,然后将其转发到相应的网络。
    • 安全过滤:网关可以作为安全控制点,对进出网络的数据进行过滤。它可以阻止某些非法的或具有潜在威胁的网络流量进入或离开网络。例如,网关可以配置访问控制列表(ACL),只允许特定 IP 地址或端口号的流量通过。

二、路由(Router)

  1. 定义
    • 路由器是一种网络设备,用于在多个网络(可以是相同类型的网络,也可以是不同类型的网络)之间转发数据包。它通过维护路由表来决定数据包的转发路径。
    • 例如,在一个大型企业网络中有多个部门的局域网,路由器可以将不同部门局域网之间的数据进行转发,并且还可以将这些局域网连接到互联网。
  2. 功能
    • 路径选择:路由器的核心功能是根据路由表选择最佳的路径来转发数据包。路由表包含了网络地址、子网掩码、下一跳地址等信息。当路由器收到一个数据包时,它会查看数据包的目的地址,然后在路由表中查找最佳的转发路径。例如,一个数据包要从本地网络发送到另一个远程网络,路由器会根据网络拓扑和链路状态等因素,选择一条最优的路径(如最短路径或者带宽最高的路径等)将数据包转发出去。
    • 网络互联:路由器能够将不同的网络连接在一起。它可以连接局域网(LAN)和广域网(WAN),或者连接多个不同的局域网。比如,一个小型办公室网络通过路由器连接到互联网服务提供商(ISP)的网络,从而实现办公室内部的计算机与互联网的连接。
    • 隔离广播域:路由器可以隔离广播域。在一个局域网中,广播消息会被发送到局域网中的所有设备。但是,当通过路由器连接不同的网络时,广播消息不会被路由器转发到其他网络,除非进行特殊配置。这有助于减少网络中的广播流量,提高网络的性能。

现在,微服务网关就起到同样的作用。前端请求不能直接访问微服务,而是要请求网关:

  • 网关可以做安全控制,也就是登录身份校验,校验通过才放行

  • 通过认证后,网关再根据请求判断应该访问哪个微服务,将请求转发过去

在SpringCloud当中,提供了两种网关实现方案:

  • Netflix Zuul:早期实现,目前已经淘汰

  • SpringCloudGateway:基于Spring的WebFlux技术,完全支持响应式编程,吞吐能力更强

课堂中我们以SpringCloudGateway为例来讲解,官方网站:

Docsicon-default.png?t=O83Ahttps://b11et3un53m.feishu.cn/wiki/UMgpwmmQKisWBIkaABbcwAPonVf#S1FjdzW92oKZCJxLgs3cKmW9nUK

2.快速入门

接下来,我们先看下如何利用网关实现请求路由。由于网关本身也是一个独立的微服务,因此也需要创建一个模块开发功能。大概步骤如下:

  • 创建网关微服务

  • 引入SpringCloudGateway、NacosDiscovery依赖

  • 编写启动类

  • 配置网关路由

2.1.创建项目

首先,我们要在hmall下创建一个新的module,命名为hm-gateway,作为网关微服务:

2.2.引入依赖

hm-gateway模块的pom.xml文件中引入依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>hmall</artifactId><groupId>com.heima</groupId><version>1.0.0</version></parent><modelVersion>4.0.0</modelVersion><artifactId>hm-gateway</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><!--common--><dependency><groupId>com.heima</groupId><artifactId>hm-common</artifactId><version>1.0.0</version></dependency><!--网关--><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></dependencies><build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

2.3.启动类

hm-gateway模块的com.hmall.gateway包下新建一个启动类:

2.4.配置路由

接下来,在hm-gateway模块的resources目录新建一个application.yaml文件,内容如下:

server:port: 8080
spring:application:name: gatewaycloud:nacos:server-addr: 192.168.150.101:8848gateway:routes:- id: item # 路由规则id,自定义,唯一uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务- Path=/items/**,/search/** # 这里是以请求路径作为判断规则- id: carturi: lb://cart-servicepredicates:- Path=/carts/**- id: useruri: lb://user-servicepredicates:- Path=/users/**,/addresses/**- id: tradeuri: lb://trade-servicepredicates:- Path=/orders/**- id: payuri: lb://pay-servicepredicates:- Path=/pay-orders/**

3.路由过滤

路由规则的定义语法如下:

spring:cloud:gateway:routes:- id: itemuri: lb://item-servicepredicates:- Path=/items/**,/search/**

其中routes对应的类型如下:

是一个集合,也就是说可以定义很多路由规则。集合中的RouteDefinition就是具体的路由规则定义,其中常见的属性如下:

四个属性含义如下:

  • id:路由的唯一标示

  • predicates:路由断言,其实就是匹配条件

  • filters:路由过滤条件,后面讲

  • uri:路由目标地址,lb://代表负载均衡,从注册中心获取目标微服务的实例列表,并且负载均衡选择一个访问。

这里我们重点关注predicates,也就是路由断言。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

权重处理

4.网关登录校验

单体架构时我们只需要完成一次用户登录、身份校验,就可以在所有业务中获取到用户信息。而微服务拆分后,每个微服务都独立部署,不再共享数据。也就意味着每个微服务都需要做登录校验,这显然不可取。

4.1.鉴权思路分析

我们的登录是基于JWT来实现的,校验JWT的算法复杂,而且需要用到秘钥。如果每个微服务都去做登录校验,这就存在着两大问题:

  • 每个微服务都需要知道JWT的秘钥,不安全

  • 每个微服务重复编写登录校验代码、权限校验代码,麻烦

既然网关是所有微服务的入口,一切请求都需要先经过网关。我们完全可以把登录校验的工作放到网关去做,这样之前说的问题就解决了:

  • 只需要在网关和用户服务保存秘钥

  • 只需要在网关开发登录校验功能

此时,登录校验的流程如图:

暂时无法在飞书文档外展示此内容

不过,这里存在几个问题:

  • 网关路由是配置的,请求转发是Gateway内部代码,我们如何在转发之前做登录校验?

  • 网关校验JWT之后,如何将用户信息传递给微服务?

  • 微服务之间也会相互调用,这种调用不经过网关,又该如何传递用户信息?

4.2.网关过滤器

登录校验必须在请求转发到微服务之前做,否则就失去了意义。而网关的请求转发是Gateway内部代码实现的,要想在请求转发之前做登录校验,就必须了解Gateway内部工作的基本原理。

如图所示:

  1. 客户端请求进入网关后由HandlerMapping对请求做判断,找到与当前请求匹配的路由规则(Route),然后将请求交给WebHandler去处理。

  2. WebHandler则会加载当前路由下需要执行的过滤器链(Filter chain),然后按照顺序逐一执行过滤器(后面称为Filter)。

  3. 图中Filter被虚线分为左右两部分,是因为Filter内部的逻辑分为prepost两部分,分别会在请求路由到微服务之前之后被执行。

  4. 只有所有Filterpre逻辑都依次顺序执行通过后,请求才会被路由到微服务。

  5. 微服务返回结果后,再倒序执行Filterpost逻辑。

  6. 最终把响应结果返回。

如图中所示,最终请求转发是有一个名为NettyRoutingFilter的过滤器来执行的,而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器,在其中实现登录校验逻辑,并且将过滤器执行顺序定义到NettyRoutingFilter之前,这就符合我们的需求了!

那么,该如何实现一个网关过滤器呢?

网关过滤器链中的过滤器有两种:

  • GatewayFilter:路由过滤器,作用范围比较灵活,可以是任意指定的路由Route.

  • GlobalFilter:全局过滤器,作用范围是所有路由,不可配置。

注意:过滤器链之外还有一种过滤器,HttpHeadersFilter,用来处理传递到下游微服务的请求头。例如org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter可以传递代理请求原本的host头到下游微服务。

其实GatewayFilterGlobalFilter这两种过滤器的方法签名完全一致:

/*** 处理请求并将其传递给下一个过滤器* @param exchange 当前请求的上下文,其中包含request、response等各种数据* @param chain 过滤器链,基于它向下传递请求* @return 根据返回值标记当前请求是否被完成或拦截,chain.filter(exchange)就放行了。*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

FilteringWebHandler在处理请求时,会将GlobalFilter装饰为GatewayFilter,然后放到同一个过滤器链中,排序以后依次执行。

Gateway中内置了很多的GatewayFilter,详情可以参考官方文档:

Docsicon-default.png?t=O83Ahttps://b11et3un53m.feishu.cn/wiki/UMgpwmmQKisWBIkaABbcwAPonVf#CbiqdfAlNoTXFCxAJeDcyiwenuc

Gateway内置的GatewayFilter过滤器使用起来非常简单,无需编码,只要在yaml文件中简单配置即可。而且其作用范围也很灵活,配置在哪个Route下,就作用于哪个Route.

例如,有一个过滤器叫做AddRequestHeaderGatewayFilterFacotry,顾明思议,就是添加请求头的过滤器,可以给请求添加一个请求头并传递到下游微服务。

使用的使用只需要在application.yaml中这样配置:

spring:cloud:gateway:routes:- id: test_routeuri: lb://test-servicepredicates:-Path=/test/**filters:- AddRequestHeader=key, value # 逗号之前是请求头的key,逗号之后是value

如果想要让过滤器作用于所有的路由,则可以这样配置:

spring:cloud:gateway:default-filters: # default-filters下的过滤器可以作用于所有路由- AddRequestHeader=key, valueroutes:- id: test_routeuri: lb://test-servicepredicates:-Path=/test/**

5.自定义过滤器

无论是GatewayFilter还是GlobalFilter都支持自定义,只不过编码方式、使用方式略有差别。

5.1自定义GlobalFilter

自定义GlobalFilter则简单很多,直接实现GlobalFilter即可,而且也无法设置动态参数:

@Component
public class PrintAnyGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 编写过滤器逻辑System.out.println("未登录,无法访问");// 放行// return chain.filter(exchange);// 拦截ServerHttpResponse response = exchange.getResponse();response.setRawStatusCode(401);return response.setComplete();}@Overridepublic int getOrder() {// 过滤器执行顺序,值越小,优先级越高return 0;}
}

http://www.lryc.cn/news/516066.html

相关文章:

  • 信号的产生、处理
  • 在Linux中,zabbix如何监控脑裂?
  • C++基础概念复习
  • Earth靶场
  • JavaScript 日期格式
  • django vue3实现大文件分段续传(断点续传)
  • xiaoya小雅超集使用夸克网盘缓存教程
  • 计算机基础知识复习1.4
  • SpringMVC(三)请求
  • Node.js应用程序遇到了内存溢出的问题
  • 如何构建云原生时空大数据平台?
  • 二极管钳位电路分享
  • 腾讯云智能结构化 OCR:驱动多行业数字化转型的核心引擎
  • 19.3、Unix Linux安全分析与防护
  • JVM对象内存结构
  • 联邦学习和大模型相结合: 数据隐私,提升训练效率,架构优化
  • 命令别名和命令历史
  • 打造三甲医院人工智能矩阵新引擎(二):医学影像大模型篇--“火眼金睛”TransUNet
  • Scade pragma: separate_io
  • IWOA-GRU和GRU时间序列预测(改进的鲸鱼算法优化门控循环单元)
  • “知识图谱AI教学辅助系统:点亮智慧学习的新灯塔
  • 产品 防尘防水IP等级 划分与实验方法
  • 【微服务】1、引入;注册中心;OpenFeign
  • 01、Docker学习,第一天:简单入门与安装
  • C++STL中iomanip的使用与细节
  • 3.C语言变量的基础概念与使用
  • Go语言中的逃逸分析:深入浅出
  • 【FlutterDart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)
  • 【论文笔记】LongLoRA: Efficient Fine-tuning of Long-Context Large Language Models
  • 数据挖掘——朴素贝叶斯分类