Spring Cloud ------ Gateway

Spring Cloud ------ Gateway
一、什么是网关

经常面试的人肯定知道,在去公司面试时,通常不会直接去面试官那里面试,而是先去前台进行询问面试官的所在地,并进行一些相关登记。而网关对于一个微服务项目来说,就类似于一个前台,打到微服务中的请求通常都需要先到网关,由网关进行一些处理后,再打到相关服务上。

网关的处理具体包括以下几个方面:

  • 权限控制:对请求进行权限校验,校验失败则直接将请求进行拦截。
  • 动态路由:根据请求信息将请求转发到对应的微服务上。
  • 负载均衡:当请求的目标服务有多个时,根据情况进行负载均衡
  • 限流:将请求按照设定的最大流量进行限流,以免各服务压力过大 

目前市面上大多数都是使用Gateway来作为微服务的网关。

二、Gateway的使用
Gateway服务的搭建

1.在微服务中使用Gateway网关,首先我们得在微服务项目中创建一个新的模块。

2.然后我们需要引入依赖,具体如下:

 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <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> 

3.然后我们需要创建一个启动类

此时,一个网关模块就创建好了,但当前网关还没有设置任何处理请求的功能,下面我们来看一下如何设置网关的功能。

Route Predicate Factories

在Java8中提供了一个函数式接口Predicate,这个接口能够校验请求中的参数,具体为通过接受一个字符串,根据字符串的特点返回一个布尔值,用来进行条件过滤。下面我们来具体使用一下这个接口。

1.首先我们来创建一个该接口的实现类

2.然后重写其中的test方法

在test中我们可以定义一些逻辑来进行条件判断,例如我们这里定义成字符串为空返回false,不为空返回true。

然后我们就可以使用这个类来进行一些参数判断了

在Predicate中还包含了许多其它方法,例如and方法,它的参数为Predicate类型 ,返回值为一个新的Predicate,这个新的Predicate的test方法返回的则是前两个Predicate的test返回值取”&&“的结果。其它方法可以参考下面的内容:

  • isEqual(Object targetRef):⽐较两个对象是否相等,参数可以为Null
  • and(Predicate other):短路与操作,返回⼀个组成Predicate
  • or(Predicate other):短路或操作,返回⼀个组成Predicate
  • test(T t):传⼊⼀个Predicate参数,⽤来做判断 
  • negate():返回表⽰此Predicate逻辑否定的Predicate

Gateway给我们提供了一个 Route Predicate Factories(路由断言工厂),里面包含了很多的Predicate来对路由进行一些规则匹配,例如Path,它能匹配指定规则的路径,Methond能够匹配指定的请求方法,还有其它的一些Predicate,大家可以去下面这个链接进行查询:

https://docs.spring.io/spring-cloud-gateway/reference/spring-cloudgateway/request-predicates-factories.html

我们可以在我们创建的Gateway模块的配置文件中来使用这些Predicate,具体使用的配置如下:

gateway: routes: # ⽹关路由配置 - id: product-service #路由ID, ⾃定义, 唯⼀即可 uri: lb://product-service #⽬标服务地址 predicates: #路由条件 - Path=/product/** - id: order-service uri: lb://order-service predicates: - Path=/order/**

配置好之后,当请求的url与predicates中对于的路由规则path匹配时,就会依据id中的服务名称,去注册中心获取对应的服务地址,然后负载均衡出一个地址并构建对应的请求去访问目标服务。

例如我们去访问下面这个地址:

http://127.0.0.1:8080/order/1

此时请求就会来到网关,在网关中进行predicate的条件判断,判断通过后去Nacos获取服务信息并负载均衡吗,然后去访问目标服务。上面地址的访问结果如下:

可以发现成功返回了数据,由此可以推断,请求成功通过网关访问到了目标服务。

如果我们的请求不符合定义的匹配规则,则不会访问到目标服务,例如我们访问下面这个 路径http://127.0.0.1:8080/feign/1(也是order-service里面的)

我们也可以配置多个predicate,例如我们再配置 一个Method,用来匹配请求的方法

此时只要请求同时匹配这两个规则才能够去访问对应的服务。 

Gateway Filter Factories 
Filter

Predicate能够设置一些请求的匹配规则,而Filter则能在请求被目标服务处理前后,添加一些逻辑。例如,我们可以在请求发送到目标服务之前,让请求新增一个参数。Filter在生效时机上可以分为Post类型和Pre类型,

Pre类型的Filter中定义的逻辑在请求处理前执行,而Post类型的则是在请求处理完成之后,数据返回给用户之前执行。在生效范围上,又可以把Filter分为GatewayFilter(作用于单个路由或者同一个分组的路由上,也就是匹配到的id是一样的)、GlobalFilter(对于每一个路由都生效,也就是每一个请求都生效)。

Gateway Filter Factories(路由过滤工厂)中为我们提供了很多的Filter,例如AddRequestParameter,它能在请求被处理之前在请求中添加一个参数,下面我们来具体使用以下。

Filter和Predicate一样,也是需要在配置文件中进行配置,具体如下:

server: port: 10030 gateway: routes: # ⽹关路由配置 - id: product-service #路由ID, ⾃定义, 唯⼀即可 uri: lb://product-service #⽬标服务地址 predicates: #路由条件 - Path=/product/** - id: order-service uri: lb://order-service predicates: - Path=/order/** filters: - AddRequestParameter=userName, bite

这里我们配置了AddRequestParameter,他在请求中添加了一个username字段,值为bite。

下面我们通过一个接口来测试一下是否真的添加了该参数

我们启动对应的服务来访问一下这个接口,打印的日志如下:

可以发现成功获取到Filter添加的参数了。在路由过滤工厂中还有许多其他的Filter,如果大家想了解更多,可以访问如下地址:

GatewayFilter Factories :: Spring Cloud Gateway

前面我们配置的Filter只能对当前的单一路由生效,如果我们想对所有路由都生效,就需要配置default-Filter,具体配置项如下:

server: port: 10030 spring: application: name: gateway cloud: nacos: discovery: server-addr: 182.92.242.181:8848 gateway: metrics: enabled: true routes: - id: order-service #路由规则id, 随便起, 不重复即可 uri: lb://order-service/ #目标服务地址 predicates: #路由条件 - Path=/order/** - After=2024-03-20T00:00:22.370856700+08:00[Asia/Shanghai] filters: - AddRequestParameter=userName, bite - name: Custom #过滤器名称 args: name: test_custom - id: product-service uri: lb://product-service/ predicates: - Path=/product/** default-filters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY 

 此时配置的Filter就对对所有路径都生效了。

GlobalFilter

在Gateway中提供了很多全局过滤器(GlobalFilter),用来实现安全监控,日志记录等功能。常见的有

 • Gateway Metrics Filter: ⽹关指标,提供监控指标

 • Forward Routing Filter:⽤于本地forword,请求不转发到下游服务器

 • LoadBalancer Client Filter: 针对下游服务, 实现负载均衡.

使用GlobalFilter 进行监控等功能需要引入下面这个依赖

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

然后在配置文件中进行配置,具体配置项如下:

spring: cloud: gateway: metrics: enabled: true #开启监控相关的全局过滤器 management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always shutdown: enabled: true

此时我们访问下面这个链接就能得到请求的监控信息:

网关地址/actuator
Filter的执行顺序

在一个路由下,可能会有多个Filter,他们的执行顺序如何呢?我们来看一下。

在请求发送到对应的服务之前,网关会去获取当前请求需要使用到的所有Filter,并将其按照Order值排序(每个Filter都必须指定一个Order值,Order值越大,执行的顺序则越靠前,反之则越靠后,路由过滤工厂给我们提供的Filter都是已经设置好Order值了),根据顺序执行Filter。如果Order值一样,则按照,defaultFilter>GatewayFilter>GlobalFilter的顺序执行。

Read more

HDFS NameNode高可用(HA)完全指南:原理、组件与实现

HDFS NameNode高可用(HA)完全指南:原理、组件与实现

HDFS NameNode高可用(HA)完全指南:原理、组件与实现 * 引言 * 一、NameNode HA架构总览 * 1.1 架构目标 * 1.2 架构图 * 1.3 核心设计思想 * 二、核心组件详解 * 2.1 组件一览表 * 2.2 JournalNode:共享存储的核心 * 工作原理 * 2.3 ZooKeeper:分布式协调者 * 2.4 ZKFC:故障转移控制器 * 2.5 DataNode的特殊角色 * 三、元数据同步机制:QJM详解 * 3.1 QJM是什么? * 3.2 写入流程 * 3.

By Ne0inhk
LeetCode算法日记 - Day 5: 长度最小的子数组、无重复字符的最长子串

LeetCode算法日记 - Day 5: 长度最小的子数组、无重复字符的最长子串

目录 1. 长度最小的子数组 1.1 题目解析 1.2 解法 1.3 代码实现 2. 无重复字符的最长子串 2.1 题目解析 2.2 解法 2.3 代码实现 1. 长度最小的子数组 209. 长度最小的子数组 - 力扣(LeetCode) 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: 输入:

By Ne0inhk
《算法题讲解指南:优选算法-前缀和》--31.连续数组,32.矩阵区域和

《算法题讲解指南:优选算法-前缀和》--31.连续数组,32.矩阵区域和

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 31. 连续数组 题目链接: 题目描述: 题目示例: 解法(前缀和+哈希表): 算法思路: C++算法代码: 算法总结及流程解析: 32. 矩阵区域和 题目链接: 题目描述: 题目示例: 解法: 算法思路: C++算法代码: 算法总结及流程解析: 结束语 31. 连续数组 题目链接: 525. 连续数组 - 力扣(LeetCode) 题目描述: 题目示例: 解法(

By Ne0inhk
算法训练之哈希表

算法训练之哈希表

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥✨✨✨✨✨✨ 个人主页✨✨✨✨✨✨         这一篇博客开启算法学习的另外一个篇章——哈希表,准备好了吗~我们发车去探索算法的奥秘啦~🚗🚗🚗🚗🚗🚗 目录 前言😁 哈希表基础概念😍    适用场景😊 实现方式😁 关键注意事项😜 容器使用参考博客🐷 两数之和😊 判断是否为字符串重排😋 存在重复元素Ⅱ🤪 字母异位词分组😀 总结🙃 前言😁 哈希表基础概念😍            哈希表是一种用于存储数据的容器,本质是通过键值对(key-value)的形式组织数据。它的核心优势在于能实现元素的快速查找,理想情况下时间复杂度可达 O(1),远超二分查找的 O(log N)。 适用场景😊         当需要频繁查找某个特定元素时(例

By Ne0inhk