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

统一服务入口-Gateway

目录

网关介绍

问题引出

API 网关

核心功能

常见网关实现

Zuul

Spring Cloud Gateway

Spring Cloud Gateway

快速使用

创建网关项目

引入网关依赖

启动类

添加 Gateway 的路由配置

测试:

Route Predicate Factories

Predicate

Route Predicate Factories

代码示例

Gateway Filter Factories(网关过滤工厂)

GatewayFilter

快速使用:

GatewayFilter

GlobalFilter

快速使用

过滤器执行顺序

自定义过滤器

自定义 GatewayFilter

定义 GatewayFilter

自定义 GlobalFilter

服务部署

完!


网关介绍

问题引出

前面的课程中,我们通过 Eureka,Nacos 解决了服务注册,服务发现的问题,使用 Spring Cloud LoadBalanced 解决了负载均衡问题,使用 OpenFeign 解决了远程调用问题。

但是,当前的所有微服务接口都是直接对外暴露的,可以直接通过外部进行访问。为了保证对外服务的安全性,服务端实现的微服务接口通常带有一定的权限校验。

由于使用了微服务模块,原本一个应用的多个模块被拆分成了多个应用,导致我们需要进行多次逻辑校验。当逻辑校验发生变化时,就需要改变多个应用

针对这个问题,常用的解决方式是使用 API 网关。

API 网关

API 网关(简称网关)也是一个服务,通常是后端服务的唯一入口。它的定义类似设计模式中的门面模式,可以理解为整个微服务架构的前台门面。所有访问微服务的外部客户端,都需要经过它来进行调度和过滤。

核心功能

1. 权限控制:作为微服务的入口,对用户进行权限校验,如果权限校验失败则进行拦截。

2. 动态路由:一切请求先经过网关,但网关不对业务进行处理,而是根据某种规则,把请求转发到某个微服务。

3. 负载均衡:当路由的目标服务有多个的时候,还需要做负载均衡。

4. 限流:请求流量过高的时候,按照网关中配置的微服务能够接收的流量进行放行,避免服务压力过大。

常见网关实现

实现网关的方式较多,技术方案较成熟,有很多开源产品,例如:Nginx,Kong,,Zuul,Spring Cloud Gateway 等。

Zuul

Spring Cloud Gateway

Spring Cloud Gateway

快速使用

在代码使用中,了解网关的功能作用。

创建网关项目

可以直接在前面的 openfeign 项目中继续完善。

引入网关依赖

启动类

添加 Gateway 的路由配置

在 application.yml 文件中,添加如下配置

配置字段说明:

1. id:路由规则的唯一标识符,用于区分不同的路由规则

2. uri:指定目标服务的地址。

            lb://   前缀表示使用负载均衡

            product-service  是目标服务在注册中心的服务名称

3. predicates(断言):定义路由匹配条件,当请求满足所有断言条件时,路由才会到对应的 uri

        Path 断言

                基于路径的匹配。  /product/** 表示匹配所有以 /product 开头的请求

工作流程:

1. 客户端请求对应 ip

2. 网关匹配到 product-service 路由规则

3. 从 Nacos 获取 product-service 的服务实例列表

4. 通过负载均衡选择一个实例

5. 将请求转发到选中的实例

测试:

启动 API 网关服务

1. 通过网关服务访问 product-service

127.0.0.1:10030/product/1001

此时的 url 符合我们刚刚在 yml 文件中配置的 Path 断言:/product/** 规则,路由转发到 product-service:http://product-service/product/1001

访问后,我们可以观察网关服务的日志,看到网关服务从 Nacos 获取服务列表:

2. 通过网关服务访问 order-service

127.0.0.1:10030/order/1

url 服务 yml 文件中配置的 Path 断言:/order/** 规则,路由转发到 order-service:http://order-service/product/1001

Route Predicate Factories

Predicate

Predicate 是 Java 8 提供的一个函数式编程接口,接收一个参数返回一个布尔值,用于条件过滤,请求参数的校验。

测试使用:

Predicate 的其他写法:

1. 内置函数(匿名内部类):

2. lambda 写法

有匿名内部类的写法,就也可以简化为 lambda 写法

再补充: s -> s.isEmpty() 也可以写成 String::isEmpty;


String::isEmpty 是一种直接方法引用。

对于一种”把接收到的参数直接当作调用者来执行某个方法“的情况,可以用方法引用来实现进一步的简写。

String::isEmpty 的工作流程:

这行代码 Predicate<String> predicate3 = String::isEmpty; 的意思是:

1. :: 是方法引用的操作符

2. String 是类名

3. isEmpty 是该类的一个实例方法

编译器理解:


Predicate 的其他方法:

组合使用示例:

List<String> list = Arrays.asList("Java", "Predicate", "Test", "API");// 1. 创建一个 "条件A" (Predicate A)
Predicate<String> lengthCheck = s -> s.length() > 4;// 2. 创建一个 "条件B" (Predicate B)
Predicate<String> startsWithJ = s -> s.startsWith("J");// 3. 在 filter 中使用
// 筛选出长度大于4的
list.stream().filter(lengthCheck).forEach(System.out::println);
// 输出: Predicate// 4. 组合使用:筛选出长度大于4,且以J开头的 (A && B)
list.stream().filter(lengthCheck.and(startsWithJ)).forEach(System.out::println);
// 输出: (无) // 5. 组合使用:筛选出长度大于4,或以J开头的 (A || B)
list.stream().filter(lengthCheck.or(startsWithJ)).forEach(System.out::println);
// 输出: Java, Predicate

静态方法:isEqual

签名:static <T> Predicate<T> isEqual(Object targetRef)

这是一个静态工厂方法,返回一个 Predicate。这个 Predicate 的作用是判断传入的参数是否等于 targetRef。让我们不必自己动手写 Lambda 表达式,而是直接调用一个方法来得到一个“现成的” Predicate 实例。

Route Predicate Factories

路由断言工厂,在 Spring Cloud Gateway 中,Predicate 提供了路由规则的匹配机制。

我们在 yml 配置文件中的断言规则只是字符串,这些字符串会被 Route Predicate Factory 读取并处理,转变为路由判断的条件。

例如,前面举例中的快速使用,Path = /product/**,就是通过 Path 属性来匹配 URL 前缀是 /product 的请求~~

这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory 实现的。

Spring Cloud Gateway 默认提供了很多 Route Predicate Factory,这些 Predicate 会分别匹配 HTTP 请求的不同属性,并且多个 Predicate 可以通过 and 逻辑进行组合。

代码示例

1. 添加 predicate 规则:

2. 测试

访问:127.0.0.1:10030/order/1

返回 404

3. 修改时间为 2024-01-01,再次访问

127.0.0.1:10030/order/1

正常返回结果

Gateway Filter Factories(网关过滤工厂)

前面的 Predicate 决定了请求由哪一个路由进行处理,如果在请求处理前后需要增加一些逻辑,这就是 Filter(过滤器)的作用范围。

Filter 分为两种类型:Pre 类型和 Post 类型。

Pre 类型过滤器:路由处理之前执行(请求转发到后端服务之前执行),在 Pre 类型过滤器中可以做鉴权,限流等~

Post 类型过滤器:请求执行完毕后,将结果返回给客户端之前执行。

Spring Cloud Gateway 中内置了很多 Filter,用于拦截和链式处理 web 请求。比如权限校验,访问超时等等功能。

Spring Cloud Gateway 从作用范围上,可以将 Filter 分为 GatewayFilter,GlobalFilter

GateFilter:应用到单个路由或者一个分组的路由上

GlobalFilter:应用到所有路由上,也就是对所有的请求生效

GatewayFilter

GatewayFilter 和 Predicate 类似,都是在 yml 配置文件中进行配置。

每个过滤器的逻辑都是固定的,比如 AddRequestParameterGatewayFilterFactory 只需要在配置文件中写 AddRequestParameter,就可以为所有的请求添加一个参数。


快速使用

在 application.yml 中添加 filter

在 product-service 中接收参数并进行打印

测试

重启 gateway 和 product-service 服务,访问请求,观察日志

127.0.0.1:10030/product/1001

控制台打印日志,接收到参数:zzz

GatewayFilter

Spring Cloud Gateway 提供了的 Filter 非常多,官方参考文档:qGatewayFilter Factories

前面的 filter 添加在指定路由下,所以只对当前路由生效,若需要对全部路由生效,可以使用

spring.cloud.gateway.default-filters

这个属性需要一个 filter 的列表

GlobalFilter

GlobalFilter 是 Spring Cloud Gateway 中的全局过滤器,它和 GatewayFilter 的作用是相同的。

GlobalFilter 通常用到所有的路由请求上,全局过滤器通常用于实现与安全性,性能监控,日志记录等相关的全局功能。

Spring Cloud Gateway 内置的全局过滤器也有很多,比如:

        GatewayMetricsFilter: 网关指标,提供监控指标

        ForwardRoutingFilter: 用于本地forword,请求不转发到下游服务器

        LoadBalancerClientFilter: 针对下游服务,实现负载均衡.

官方文档:GlobalFiter

快速使用

1. 引入依赖

2. 添加配置

配置讲解:

3. 测试

访问:127.0.0.1:10030/actuator 显示所有监控的信息链接

过滤器执行顺序

一个项目中,既有 GatewayFilter,又有 GlobalFilter 时,执行先后顺序:

请求路由后,网关会把当前项目中的 GatewayFilter 和 GlobalFilter 合并到一个过滤器链(集合)中,并进行排序,一次执行过滤器。

每一个过滤器都必须有一个 int 类型的 order 值,默认值为 0,表示该过滤的优先级。

order 越小,优先级越高,执行顺序就越靠前

Filter 通过实现 Order 接口,或者添加 @Order 注解来指定 order 的值。

Spring Cloud Gateway 提供的 Filter 由 Spring 指定。用户也可以自定义 Filter,由用户自行指定。

当过滤器的 order 值一样的时候,会按照:defaultFilter -> GatewayFilter -> GlobalFilter 的顺序执行

自定义过滤器

Spring Cloud Gateway 提供了过滤器的扩展,可以根据实际业务自定义过滤爱情,同样也是支持 GatewayFilter 和 GlobalFilter 两种

自定义 GatewayFilter

需要实现对应的接口 GatewayFilterFactory,SpringBoot 默认帮我们实现的抽象类是 AbstractGatewayFilterFactory,可以直接使用

定义 GatewayFilter

CustomGatewayFilter 继承 AbstractGatewayFilterFactory,实现 Ordered 接口

AbstractGatewayFilterFactory 需要一个配置类,来接收 yaml 传来的参数,它包含了过滤器所需的配置属性。在Spring Cloud Gateway 中,配置文件中的配置项慧自动映射到这个类中。例如:

CustomConfig 中有一个 name 属性,name 的值可以从 yaml 配置文件中获取并传递到过滤器中。

实现对应的方法,过滤器也需要 Spring 容器帮我们管理:

此外,还需要补充一个 CustomGatewayFilterFactory 的构造方法

在这个构造方法中,调用父类 AbstractGatewayFilterFactory 的构造方法,并传入了 CustomConfig.class 作为参数。

使用这个构造方法,可以使得 Spring Cloud Gateway 能够为过滤器解析配置,告诉 Spring 在 Yaml 文件中如何映射到自定义的配置类。

配置优先级:

然后实现 apply 方法,返回值为 GatewayFilter,new 一个 GatewayFilter 匿名内部类

在 apply 方法中,需要定义自定义过滤器的核心逻辑。apply 方法接收一个 CustomConfig 参数,表示该过滤器的配置。

ServerWebExchange:HTTP 请求-相应交互的契约,提供对 HTTP 请求和相应的访问,服务器端请求属性,请求示例,响应实例类等,类似 Context

其中有如下方法等:

GatewayFilterChain,过滤器链,用于调用下一个过滤器,chain.filter(exchange) 就可以执行过滤器链中的其他过滤器。

Mono:Reactor 核心类,数据流发布者,Mono 最多只触发一个时间,可以把 Mono 用在异步任务完成时发出通知。

Mono.fromRunnable:创建一个包含 Runnable 元素的数据流。then 方法表示过滤链执行完毕后进行的操作。

补充说明:

        1.  类名统一以 GatewayFilterFactory 结尾。因为默认情况下,过滤器中的 name 会采用该定义类的前缀。这里的 name = Custom(yml 配置文件中使用)

        2. apply 方法中,同时包含 Pre 和 Post 过滤,then 方法中是请求执行结束之后处理的。

        3. CustomConfig 是一个配置类,该类只有一个属性 name,和 yml 的配置对应。

        4. 该类需要交给 Spring 管理,所以需要加 @Service 注解。

        5. getOrder 表示该过滤器的优先级,值越大,优先级越低。


配置过滤器

​​​​​​​


测试:

重启服务,访问接口,观察日志。

127.0.0.1:10030/product/1001

自定义 GlobalFilter

GlobalFilter 实现比较简单,不需要额外的配置,只需要实现 GlobalFiler 接口,自动会过滤所有的 Filter

重启服务,访问接口,观察日志:

服务部署

1. 修改数据库,Nacos 相关配置

2. 对三个微服务进行打包

3. 上传 jar 包到 Linux 服务器

4. 启动 Nacos (启动前最好将 data 数据删除掉)

5. 启动服务

测试,符合预期~

完!

http://www.dtcms.com/a/569320.html

相关文章:

  • 济南做网站的公司哪家好网站建设工作半年通报
  • 为什么要GetWorld()?
  • HBase安装配置
  • 【开题答辩实录分享】以《基于Java的校园心理咨询服务系统的设计与实现》为例进行答辩实录分享
  • 佛山网站建设的品牌2345网址导航下载安装到桌面
  • 场外衍生品系统开发实战:TRS收益互换与场外个股期权架构解析
  • 网站需求分析模板浅谈电子商务网站建设与规划
  • Spring Boot整合MQTT
  • 《Nginx进阶实战:反向代理、负载均衡、缓存优化与Keepalived高可用》
  • 第6章 结构体与方法
  • 为什么 transformers 要 import TensorFlow
  • 网站建设要学哪些软件偃师网络营销的概念
  • 【AI学习-comfyUI学习-翻译文本工作流-各个部分学习-第二步】
  • 短期与长期利益平衡
  • 简单网站建设 有教程网络服务费绩效目标申报表
  • 网站建设技术知乎中文域名的网站有哪些
  • 二十一、STM32的ADC(一)(ADC介绍)
  • AWS helmchart包适CCE
  • 【LeetCode】98. 验证二叉搜索树
  • 摄影师网站html52017 wordpress宽屏主题
  • 【软件安全】什么是XSS(Cross-Site Scripting,跨站脚本)?
  • 2025年Java面试指南(持续更新)
  • leetcode 190. 颠倒二进制位 python
  • 网站用什么域名东莞网络营销策划
  • springboot 工具类 日期时间列表工具类详解:高效处理日期范围的利器
  • MYSQL第四次作业
  • 某游戏大厂分布式系统经典实战面试题解析
  • 某游戏大厂计算机网络面试问题深度解析(一)
  • C#基础:如何从现有类库复制一个新的类库,并且加入解决方案
  • C# 中 Entity Framework (EF) 和 EF Core 里的 `AsNoTracking` 方法