1.基本概述
GateWay用于在微服务架构中提供统一的入口点,对请求进行路由,过滤和处理。它就像是整个微服务系统的大门,所有外部请求都要通过它才能访问到后端的各个微服务。
2.核心概念
2.1路由(Route)
路由是Spring Cloud gateWay中最基本的构建块,它由一个ID,一个目标URI(不是URL,URL是URI的一种),一组断言和一组过滤器组成。当一个请求满足路由中的所有断言是,该请求会被路由到指定的URI中。
它定义了请求从网关到目标服务的映射规则,决定了请求将被转发到哪个具体的微服务。
2.2断言(Predicate)
断言是Java8中java.util.function.Predicate的示例。在Spring Cloud Gateway里,它用于匹配HTTP请求的条件。只有当请求满足断言所定义的条件时,才会被路由到相应的目标服务。
它是用来帮助网关判断是否将请求路由到特定的服务。可以根据请求的多种属性进行匹配,如请求路径、请求方法、请求头、请求参数等。
2.3过滤(Filter)
过滤器是 Spring Cloud Gateway 中用于修改请求和响应的组件。可以在请求被路由到目标服务之前(前置过滤器)或之后(后置过滤器)对请求和响应进行处理。
它实现诸如请求参数修改、请求头添加、限流、熔断、日志记录等功能,增强网关的功能和安全性。
3.工作流程
客户端将请求发送给SpringCloud GateWay,如果GateWay Handler Mapping确定这个请求和一个路由匹配,它将此请求发送给GatWay Web Handler进行处理。此时GatWay Web Handler就会处理请求,通过Filter Chain来进行处理,这个过滤器链会在请求路由前后都执行。简而言之就是通过一连串的Filter处理匹配到特定规则Predicates的请求。
基于上面的原理图,下面进一步查看其流程图
执行流程大致如下:
1. Gateway Client向Gateway Server发送请求。
2. 请求被HttpWebHandlerAdapter提取组装成网关上下文。
3. 网关上下文传递到DispatcherHandler,由其将请求分发给RoutePredicateHandlerMapping。
4. RoutePredicateHandlerMapping进行路由查找,依据路由断言判断路由可用性。
5. 断言成功时,FilteringWebHandler创建过滤器链并调用。
6. 请求依次经过PreFilter、微服务、PostFilter的方法后返回响应。
4.搭建网关微服务
先导入相关依赖
<dependencies>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--eureka-client gateWay作为网关,也要注册进服务中心-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- gateway和web不能同时存在,即web相关jar包不能导入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
然后编写启动类
@SpringBootApplication
@EnableDiscoverClient
public class GateWayApplication{
public static void main(String[] args){
SpringApplication.run(GateWayApplication.class,args);
}
}
编写yml配置文件
server:
port: 9527 # 配置网关服务监听的端口号为9527
spring:
application:
name: service - gateway # 配置Spring应用的名称为service - gateway
cloud:
gateway:
routes:
- id: consumer_route # 路由id,一般保证唯一即可
uri: http://localhost:80 # 路由目标地址,这里是本地80端口,硬编码形式(不推荐)
predicates:
- Path=/api/consumer/** # 断言规则,匹配以/api/consumer/开头的请求路径
filters:
- StripPrefix=1 # 过滤器,在请求转发到目标服务前,去掉一层路径,这里去掉的是/api
- id: provider_route
uri: lb://service-provider # 使用负载均衡(lb)访问名为service-provider的微服务,动态路由(推荐)
predicates:
- Path=/provider/** # 断言规则,匹配以/provider/开头的请求路径
eureka:
client:
register-with-eureka: true # 配置向Eureka注册中心注册自身服务实例
fetch-registry: true # 配置从Eureka注册中心拉取服务注册信息
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka # Eureka注册中心的地址
动态路由中的lb属于GateWay的关键字,代表是动态uri,即代表使用 的是服务注册中心的微服务名,它默认开启使用负载均衡机制。
5.断言详讲
我们重点讨论的是内置断言,即已经实现好的断言,而非自己定义的断言。
5.1.After
After 在指定时间之后,顾名思义就是只有在指定时间之后的请求才会生效。After后面跟的是一个时间
配置文件如下
predicates:
- Path=/api/consumer/**
- After=2023-05-16T20:29:54.475+08:00[GMT+08:00]
5.2.Before
before 指定时间之前只有在指定时间之前的请求才会生效。
在配置文件里面,我们配置如下
predicates:
- Path=/api/consumer/**
- Before=2023-05-16T20:29:54.475+08:00[GMT+08:00]
5.3.Between
between 需要在设定的时间范围之内才能进行请求转发。
在配置文件里面,我们配置如下
predicates:- Path=/api/consumer/**
- Between=2023-05-16T20:19:54.475+08:00[GMT+08:00],2023-05
16T20:32:54.475+08:00[GMT+08:00]
5.4.Cookie
要求请求中包含指定Cookie名和满足特定正则要求的值,Cookie必须有两个值,第一个Cookie包含的参 数名,第二个表示参数对应的值,可以是具体的值,也可以是正则表达式。 在配置文件里面,我们配置如下:
predicates:
- Path=/api/consumer/**
- Cookie=username,eric
5.5.Header
表示请求头中必须包含的内容。注意:参数名和参数值之间依然使用逗号,参数值可以写具体的值,也可 以使用正则表达式。如果Header只有一个值表示请求头中必须包含的参数。如果有两个值,第一个表示请 求头必须包含的参数名,第二个表示请求头参数对应值。
配置如下
predicates:
- Path=/api/consumer/**
- Header=name,james
5.6.Host
匹配请求参数中Host参数的值,可以有多个,使用逗号隔开**表示支持模糊匹配。
在配置文件里面我们进行如下配置:
predicates:
- Path=/api/consumer/**
- Host=127.0.0.1:8080,**.test.com
5.7.Method
Method表示请求方式。支持多个值,使用逗号分隔,多个值之间为or条件。
在配置文件里面我们进行如下配置:
predicates
- Path=/api/consumer/**
- Method=GET # 只允许使用GET请求方式
5.8.Query
要求请求必须携带对应的参数。
我们在配置文件里面我们进行如下配置:
predicates:
- Path=/api/consumer/**
- Query=age,18
请求的URL要在后面用?拼接该参数才能访问到
5.9.RemoteAddr
允许访问的客户端地址,不能使用类似ocahost这种。
在配置文件里面我们配置如下:
predicates
- Path=/api/consumer/*
- RemoteAddr=127.0.0.1