1. 简介

Spring Cloud Gateway是Spring Cloud的一个全新项目,基于Spring5.0 + Spring Boot2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式

它基于WebFlux框架实现,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty

其核心是一系列的过滤器,可以将客户端的请求转发到不同的微服务,是整个微服务API请求的入口,可以实现用户的验证登录、解决跨域、日志拦截、权限控制、限流、熔断、负载均衡、黑名单与白名单机制等功能

具备一些网关的高级功能:动态路由、限流、路径重写等

工作原理:

Spring Cloud Alibaba入门十二:Spring Cloud Gateway的使用_Spring cloud

客户端向 Spring Cloud Gateway 发出请求.如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序.此处理程序通过特定于请求的过滤器链运行请求.过滤器被虚线分隔的原因是过滤器可以在发送代理请求之前和之后运行逻辑.执行所有“预”过滤器逻辑.然后进行代理请求.发出代理请求后,将运行“post”过滤器逻辑

2. 三大核心概念

1.Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由,目标URI会被访问.

2.Predicate(断言):这是一个java 8的Predicate,可以使用它来匹配来自HTTP请求的任何内容,如:请求头和请求参数.断言的输入类型是一个ServerWebExchange.

3.Filter(过滤器):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者后对请求进行修改.

总结:web请求,通过一些匹配条件,定位到真正的服务节点.并在这个转发过程的前后,进行一些精细化控制.predicate就是匹配条件,而filter,就可以理解为一个无所不能的拦截器.有了这两个元素,再加上目标URI,就可以实现具体的路由了

Spring Cloud Alibaba入门十二:Spring Cloud Gateway的使用_Spring cloud_02

2.1 Predicate匹配规则

每一个Predicate​的使用,你可以理解为:当满足这种条件后才会被转发,如果是多个,那就是都满足的情况下被转发,当​Predicates​​配置项只配置了一个​Predicate​​​且没有配置​​Path​​​时,​​Path​​​的默认值为​​/**​

Spring Cloud Alibaba入门十二:Spring Cloud Gateway的使用_Spring cloud_03

2.1.1 Path 方式匹配转发

spring:
application:
name: spring-cloud-gateway-demo
cloud:
gateway:
routes:
- id: blog
uri: https://blog.51cto.com/abcd
predicates:
# 匹配路径转发,当且仅当访问路径是/myblog/*、/demo/list及/bus/**时,才转发该请求
# segment是一个特殊的占位符,表示单层路径匹配,而/**则是多层路径的匹配
- Path=/myblog/{segment},/demo/list,/bus/**

- id: blog-ext
uri: https://blog.51cto.com/abcd
predicates:
# 匹配路径转发,多个路径使用逗号分隔即可
- Path=/abcd/**,/666/**
# 端口号
server:
port: 8090

当访问http://localhost:8090/myblog.html时就会被自动转发到​​​https://blog.51cto.com/abcd​​​

当访问​http://localhost:8090/abcd/任意字符   时会被自动转发到​​​​​https://blog.51cto.com/abcd​​​,这里只要端口号后面的开始路径匹配​/abcd就可以了

2.1.2 Host 方式匹配转发

​Spring Cloud Gateway​可以根据​Host​主机名进行匹配转发,如果我们的接口只允许​**.678910.top​域名进行访问,那么配置如下所示:


spring:
cloud:
gateway:
routes:
- id: blog
uri: https://blog.51cto.com/abcd
predicates:
- Host=**.678910.top

2.1.3 datetime 方式匹配转发

After:满足请求时间在指定的时间之后

spring:
cloud:
gateway:
routes:
- id: after_route
uri: lb://demo-service
predicates:
# 当且仅当请求时的时间在配置的时间之后,才转发该请求,如果请求时的时间不是After配置的时间,则会返回404 not found
- After=2021-11-01T16:10:49.023+08:00[Asia/Shanghai]

小技巧:可以使用代码生成带有时区的当前时间

import java.time.ZonedDateTime;

public class Test {
public static void main(String[] args) {
System.out.println(ZonedDateTime.now());
}
}

Before:满足请求时间在指定的时间之前

spring:
cloud:
gateway:
routes:
- id: before_route
uri: lb://demo-service
predicates:
# 当且仅当请求时的时间在配置的时间之前,才转发该请求
- Before=2021-11-01T16:10:49.023+08:00[Asia/Shanghai]

Between:满足请求时间在指定的时间之间

spring:
cloud:
gateway:
routes:
- id: between_route
uri: lb://demo-service
predicates:
# 当且仅当请求时的时间在配置的时间段时,才转发该请求
- Between=2021-11-01T16:10:49.023+08:00[Asia/Shanghai], 2028-08-02T12:10:36.023+08:00[Asia/Shanghai]

2.1.4 Cookie 方式匹配转发

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: lb://demo-service
predicates:
# 当且仅当请求带有名为qfx,并且值符合正则表达式 ch.p 的Cookie时,才转发该请求
- Cookie=qfx, ch.p

2.1.5 Header 方式匹配转发

spring:
cloud:
gateway:
routes:
- id: header_route
uri: lb://demo-service
predicates:
# 当且仅当请求带有名为X-Request-Id,并且值符合正则表达式 \d+ 的Header时,才转发该请求
- Header=X-Request-Id, \d+

2.1.6 Host 方式匹配转发

spring:
cloud:
gateway:
routes:
- id: host_route
uri: lb://demo-service
predicates:
# 当且仅当名为Host的Header符合**.678910.top或**.678910.com时,才转发该请求
# 例如:www.678910.top、test.678910.top、www.678910.com等Host就满足该匹配
- Host=**.678910.top,**.678910.com

2.1.7 Method 方式匹配转发

spring:
cloud:
gateway:
routes:
- id: method_route
uri: lb://demo-service
predicates:
# 当且仅当HTTP请求方法为GET时,才转发该请求,
- Method=GET

2.1.8 Query 方式匹配转发

示例一:

spring:
cloud:
gateway:
routes:
- id: query_route
uri: lb://demo-service
predicates:
# 当且仅当请求带有名为qfx的参数,才转发该请求
- Query=qfx

示例二:

spring:
cloud:
gateway:
routes:
- id: query_route
uri: lb://demo-service
predicates:
# 当且仅当请求带有名为age的参数,且参数值与正则表达式 va. 相匹配,才转发该请求
- Query=age, va.

2.1.9 RemoteAddr 方式匹配转发

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: lb://demo-service
predicates:
# 当且仅当请求IP是192.168.1.101/200网段,例如192.168.1.116,才转发该请求
- RemoteAddr=192.168.1.101/20

2.1.10 Weight 权重匹配转发

该​​Weight​​路线谓词工厂有两个参数​:group​​和​​weight​(一个int).权重是按组计算的,相同组的一起计算

spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2

该路由会将约 80% 的流量转发到​​weighthigh.org​,将约 20% 的流量​​转发​​到​​weightlow.org​

2.1.11 组合示例

相同的​Predicate​也可以配置多个,请求的转发是必须满足所有的​Predicate​后才可以进行路由转发

spring:
cloud:
gateway:
routes:
- id: blog
uri: https://blog.51cto.com/abcd
predicates:
# 需满足请求方式是GET,Host为**.678910.top,且是192.168.1.156/188之间的网段才进行转发
- Method=GET
- Host=**.678910.top
- RemoteAddr=192.168.1.156/188

3 官方文档

官方文档传送门 ===>《​​Spring Cloud Gateway官方文档​​》

4. 使用

首先参照《​​Spring Cloud Alibaba入门一:创建Maven依赖管理项目​​​》创建一个子项目,然后参照《​​Spring Cloud Alibaba入门二:Nocas注册中心​​》引入Spring Cloud和Nacos依赖,下面来进行Gateway子项目配置

4.1 pom.xml

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<artifactId>qfx-gateway</artifactId>
<name>qfx-gateway</name>
<description>这是一个使用Gateway的示例</description>

<parent>
<groupId>com.qfx.springcloud</groupId>
<artifactId>qfxSpringCloudAlibabaDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<dependencies>
<!-- 1.引入gateway依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!-- 2.引入Nacos服务注册发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>

4.2 bootstrap.yml

# 配置Nacos信息
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos

4.3 application.yml

server:
port: 8090

spring:
application:
name: qfx-gateway
cloud:
gateway:
discovery:
locator:
# 开启服务以id去注册中心获取转发地址
enabled: true
routes:
# 路由ID(唯一)
- id: qfx-product
# 转发地址(目标服务地址),这里采用负载均衡的形式指定到注册中心的服务名
uri: lb://product-service
# 过滤器
filters:
# 过滤URL路径前缀的个数,实现映射路径中地址的去除
- StripPrefix=1
# 匹配规则
predicates:
# 断言,匹配路径
- Path=/product/**

- id: route-001 # 路由ID(唯一)
uri: https://www.163.com/ # 转发地址(目标服务地址)
predicates: # 匹配规则
- Path=/testroute01/** # 断言,匹配路径

4.4 创建Springboot启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayRunApp {

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

4.5 启动项目

Gateway子项目、product子项目、Nacos都要启动

Spring Cloud Alibaba入门十二:Spring Cloud Gateway的使用_Spring cloud_04

4.6 测试

请求:

http://127.0.0.1:8090/product/book/add?bookName=三体

实际请求地址:

http://192.168.1.197:8011/book/add?bookName=三体  或者   http://192.168.1.197:8012/book/add?bookName=三体

因为采用了启动了两个实例,请求的时候采用了负载均衡机制

Spring Cloud Alibaba入门十二:Spring Cloud Gateway的使用_Spring cloud_05

请求:

http://127.0.0.1:8090/testroute01

实际请求地址:

https://163.com

会直接跳转到 https://163.com 这个网站