1. 概述简介

1.1. 官网

上一代zuul 1.X:https://github.com/Netflix/zuul/wiki

当前gateway:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

1.2. 是什么?

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;
但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,
那就是SpringCloud Gateway一句话:gateway是原zuul1.x版的替代

1.2.1. 概述

Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。
Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gJGNStlB-1671265209950)(https://typora-image-bed-1308219393.cos.ap-guangzhou.myqcloud.com/study-diary/20221011211603.png)]

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

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

1.2.2. 一句话

SpringCloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。

源码架构:

1.3. 能干嘛?

反向代理

鉴权

流量控制

熔断

日志监控

1.4. 微服务架构中网关在哪里

1.5. 有Zuul了怎么又出来了gateway

1.5.1. 我们为什么选择Gateway?

a> neflix不太靠谱,zuul2.0一直跳票,迟迟不发布

一方面因为Zuul1.0已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。
而且很多功能Zuul都没有用起来也非常的简单便捷。

Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布了最新的 Zuul 2.x,
但 Spring Cloud 貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?

多方面综合考虑Gateway是很理想的网关选择。

b> SpringCloud Gateway具有如下特性

基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
动态路由:能够匹配任何请求属性;
可以对路由指定 Predicate(断言)和 Filter(过滤器);
集成Hystrix的断路器功能;
集成 Spring Cloud 服务发现功能;
易于编写的 Predicate(断言)和 Filter(过滤器);
请求限流功能;
支持路径重写。

c> SpringCloud Gateway 与 Zuul的区别

在SpringCloud Finchley 正式版之前,Spring Cloud 推荐的网关是 Netflix 提供的Zuul:

1、Zuul 1.x,是一个基于阻塞 I/ O 的 API Gateway

2、Zuul 1.x 基于Servlet 2. 5使用阻塞架构它不支持任何长连接(如 WebSocket) Zuul 的设计模式和Nginx较像,每次 I/ O 操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是Nginx 用C++ 实现,Zuul 用 Java 实现,而 JVM 本身会有第一次加载较慢的情况,使得Zuul 的性能相对较差。

3、Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较 Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试, Spring Cloud Gateway 的 RPS(每秒请求数)是Zuul 的 1. 6 倍。

4、Spring Cloud Gateway 建立 在 Spring Framework 5、 Project Reactor 和 Spring Boot 2 之上, 使用非阻塞 API。

5、Spring Cloud Gateway 还 支持 WebSocket, 并且与Spring紧密集成拥有更好的开发体验

1.5.2. Zuul1.x模型

Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet IO处理模型。

学过尚硅谷web中期课程都知道一个题目,Servlet的生命周期?servlet由servlet container进行生命周期管理。
container启动时构造servlet对象并调用servlet init()进行初始化;
container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。
container关闭时调用servlet destory()销毁servlet;

上述模式的缺点:
servlet是一个简单的网络IO模型,当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(比如抽风用jemeter压),线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势

所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即spring实现了处理所有request请求的一个servlet(DispatcherServlet)并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端

1.5.3. GateWay模型

WebFlux是什么?

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-new-framework

说明:

传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的。
但是
在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring5必须让你使用java8)

Spring WebFlux 是 Spring 5.0 引入的新的响应式框架,区别于 Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于 Reactor 来实现响应式流规范。

2. 三大核心概念

Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由

Predicate(断言)

参考的是Java8的java.util.function.Predicate
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由

Filter(过滤)

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

总体

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

3. Gateway工作流程

官网总结

客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。

Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

核心逻辑:路由转发+执行过滤器链

4. 入门配置

4.1. 新建Module

首先在cloud2020工程下新建一个module,模块名称叫做:cloud-gateway-gateway9527

第1步:

第2步:

第3步:

4.2. pom

<?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>mscloud03</artifactId><groupId>com.atguigu.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>cloud-gateway-gateway9527</artifactId><dependencies><!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--eureka-client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --><dependency><groupId>com.atguigu.springcloud</groupId><artifactId>cloud-api-commons</artifactId><version>${project.version}</version></dependency><!--一般基础配置类--><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><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

4.3. yml

在src/main/resources/目录下创建application.yml配置文件

server:port: 9527spring:application:name: cloud-gatewayeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内register-with-eureka: truefetch-registry: trueservice-url:defaultZone: http://eureka7001.com:7001/eureka

4.4. 业务类

网关服务没有业务类

4.5. 主启动类

在com.atguigu.springcloud模块下面创建一个启动类

package com.atguigu.springcloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;/*** @auther zzyy* @create 2020-02-06 10:17*/
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527
{public static void main(String[] args){SpringApplication.run(GateWayMain9527.class,args);}
}

4.6. 9527网关如何做路由映射?

我们不想通过暴露8001端口去访问cloud-provider-payment8001服务的PaymentController里面的getPaymentLb和getPaymentById方法

我们目前不想暴露8001端口,希望在8001外面套一层9527,我们应该怎么办呢?

4.7. YML新增网关配置

在cloud-gateway-gateway9527模块的application.yml配置文件中新增如下的网关配置

spring:application:name: cloud-gatewaycloud:gateway:routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名uri: http://localhost:8001          #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route2    #路由的ID,没有固定规则但要求唯一,建议配合服务名uri: http://localhost:8001          #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由

4.8. 测试

启动cloud-eureka-server7001

启动cloud-provider-payment8001

启动cloud-gateway-gateway9527

如果启动成功,在浏览器访问:http://eureka7001.com:7001,就可以看到如下图所示

踩坑:注意我们的cloud-gateway-gateway9527不能引入如下的web依赖,否则我们启动网关服务的时候会报错:Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.

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

访问说明:

我们在添加网关之前,访问的地址是:http://localhost:8001/payment/get/31

在添加网关之后,访问的地址是:http://localhost:9527/payment/get/31

4.9. YML配置说明

Gateway网关路由有两种配置方式:

  • 在配置文件yml中配置(就是前面我们的步骤)
  • 代码中注入RouteLocator的Bean

这里我们说一下第二种方式:代码中注入RouteLocator的Bean

官网案例:

假设我们现在有一个这样的业务需求:通过9527网关访问到外网的百度新闻网址:http://news.baidu.com/guonei

实现步骤:我们在cloud-gateway-gateway9527的com.atguigu.springcloud.config包下面新建如下的配置类

package com.atguigu.springcloud.config;import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @auther zzyy* @create 2020-02-06 11:26*/
@Configuration
public class GateWayConfig
{/*** 配置了一个id为route-name的路由规则,* 当访问地址 http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei* @param builder* @return*/@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder){RouteLocatorBuilder.Builder routes = builder.routes();routes.route("path_route_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();return routes.build();}@Beanpublic RouteLocator customRouteLocator2(RouteLocatorBuilder builder){RouteLocatorBuilder.Builder routes = builder.routes();routes.route("path_route_atguigu2", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();return routes.build();}
}

然后重启cloud-gateway-gateway9527,在浏览器访问:http://localhost:9527/guonei,发现跳转到了百度新闻的国内栏目

5. 通过微服务名实现动态路由

默认情况下Gateway会根据注册中心注册的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

步骤:

启动一个eureka server7001,然后启动两个服务的提供者cloud-provider-payment8001和cloud-provider-payment8002

修改cloud-gateway-gateway9527的application.yml配置文件

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。

lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri

重启cloud-gateway-gateway9527,然后在浏览器访问:http://localhost:9527/payment/lb ,如果成功访问说明我们的动态路由配置成功了,并且我们会发现多次刷新会在8001和8002两个端口来回切换,这说明达到了负载均衡的效果

6. Predicate的使用

6.1. 是什么?

启动我们的gateway9527,查看idea的控制台打印的日志如下

6.2. Route Predicate Factories这个是什么东东?

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。
Spring Cloud Gateway包括许多内置的Route Predicate工厂。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合

Spring Cloud Gateway 创建 Route 对象时, 使用 RoutePredicateFactory 创建 Predicate 对象,Predicate 对象可以赋值给 Route。 Spring Cloud Gateway 包含许多内置的Route Predicate Factories。

所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。

6.3. 常用的Route Predicate

6.3.1. After Route Predicate

我们的问题是:上述这个After好懂,这个时间串?

package com.atguigu.test;import java.time.ZoneId;
import java.time.ZonedDateTime;/*** @auther zzyy* @create 2019-12-02 17:37*/
public class ZonedDateTimeDemo
{public static void main(String[] args){ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区System.out.println(zbj);
//        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//        System.out.println(zny);}
}

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

6.3.2. Before Route Predicate

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

6.3.3. Between Route Predicate

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

6.3.4. Cookie Route Predicate

Cookie Route Predicate需要两个参数,一个是 Cookie name ,一个是正则表达式。路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行

application.yml配置如下

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]- Cookie=username,zzyyeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

使用curl工具去进行访问

不带cookie访问 ,如下图所示

$ curl http://localhost:9527/payment/lb

带上cookies访问,如下图所示

$ curl http://localhost:9527/payment/lb --cookie "username=zzyy

加入curl返回中文乱码的问题可以参考:https://blog.csdn.net/leedee/article/details/82685636 进行解决

6.3.5. Header Route Predicate

两个参数:一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

application.yml配置如下

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为正整数的正则表达式

使用curl工具进行测试,如下图所示

$ curl http://localhost:9527/payment/lb -H "X-Request-Id:123"

6.3.6. Host Route Predicate

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用.号作为分隔符。它通过参数中的主机地址作为匹配规则。

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式- Host=**.atguigu.comeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

使用curl工具进行测试,效果如下图所示

#正确
$ curl http://localhost:9527/payment/lb -H "Host: www.atguigu.com"
#正确
$ curl http://localhost:9527/payment/lb -H "Host: java.atguigu.com"
#错误
$ curl http://localhost:9527/payment/lb -H "Host: java.atguigu.net"

6.3.7. Method Route Predicate

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host=**.atguigu.com- Method=GETeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

使用curl工具进行测试,效果如下图所示

#正确
$ curl http://localhost:9527/payment/lb
#错误
$ curl -X -POST http://localhost:9527/payment/lb

6.3.8. Path Route Predicate

application.yml配置如下

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host=**.atguigu.com#- Method=GETeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

6.3.9. Query Route Predicate

支持传入两个参数,一个是属性名,一个为属性值,属性值可以是正则表达式。

application.yml配置如下:

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,时间相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host=**.atguigu.com#- Method=GET- Query=username, \d+  # 要有参数名username并且值还要是正整数才能路由eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

使用curl工具进行测试

$ curl http://localhost:9527/payment/lb?username=31
$ curl http://localhost:9527/payment/lb?username=-31

6.3.10. 小总结

server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能routes:- id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/**         # 断言,路径相匹配的进行路由#- After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由#- Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 断言,路径相匹配的进行路由#- Between=2020-02-02T17:45:06.206+08:00[Asia/Shanghai],2020-03-25T18:59:06.206+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式#- Host=**.atguigu.com#- Method=GET#- Query=username, \d+  # 要有参数名username并且值还要是整数才能路由eureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。

7. Filter的使用

7.1. 是什么?

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。

Spring Cloud Gateway 内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生

7.2. Spring Cloud Gateway的Filter

生命周期,Only Two

  • pre
  • post

种类,Only Two

  • GatewayFilter

    官方文档地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#the-addrequestparameter-gatewayfilter-factory

    31种之多。。。。。

  • GlobalFilter

7.3. 常用的GatewayFilter

AddRequestParameter

application.yml配置如下

server:port: 9588spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能lower-case-service-id: true #使用小写服务名,默认是大写routes:- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名uri: lb://cloud-provider-payment #匹配后的目标服务地址,供服务的路由地址#uri: http://localhost:8001 #匹配后提供服务的路由地址filters:- AddRequestParameter=X-Request-Id,1024 #过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为1024predicates:- Path=/paymentInfo/**        # 断言,路径相匹配的进行路由- Method=GET,POSTeureka:instance:hostname: cloud-gateway-serviceclient: #服务提供者provider注册进eureka服务列表内service-url:register-with-eureka: truefetch-registry: truedefaultZone: http://eureka7001.com:7001/eureka

其他种类的GatewayFilter 请自行阅读官方文档学习。

7.4. 自定义过滤器

我们自定义一个全局GlobalFilter

两个主要接口介绍:

  • GlobalFilter
  • Ordered

能干嘛?

  • 全局日志记录
  • 统一网关鉴权

案例代码:我们在cloud-gateway-gateway9527的com.atguigu.springcloud.filter包下面创建一个类去自定义过滤器

package com.atguigu.springcloud.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Date;/*** @auther zzyy* @create 2020-02-21 16:40*/
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered
{@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){log.info("***********come in MyLogGateWayFilter:  "+new Date());String uname = exchange.getRequest().getQueryParams().getFirst("uname");if(uname == null){log.info("*******用户名为null,非法用户,o(╥﹏╥)o");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder(){return 0;}
}

测试:

首先启动如下的服务

在浏览器访问如下的这些地址:

正确:http://localhost:9527/payment/lb?uname=z3

错误:http://localhost:9527/payment/lb

错误:http://localhost:9527/payment/lb?password

我们发现只有满足了自定义过滤器里面的条件才能路由转发到我们的微服务,如果不满足则无法正常转发路由

12-Gateway新一代网关相关推荐

  1. gateway sentinel 熔断 不起作用_微服务Gateway新一代网关

    上篇: https://zhuanlan.zhihu.com/p/183930681​zhuanlan.zhihu.com 一.概述简介 1.官网 上一代zuul 1.x:Netflix/zuul 当 ...

  2. 十二、Gateway新一代网关

    1.概述 1)是什么? gateway是zuul1.x版的替代 GateWay是在Spring生态系统之上构建的API网关服务,基于Spring 5 , Spring Boot2 和 Project ...

  3. 【Spring Cloud Gateway 新一代网关】—— 每天一点小知识

  4. Spring Cloud(10)——新一代网关Spring Cloud Gateway

    文章目录 Spring Cloud(10)--新一代网关Spring Cloud Gateway 1.背景知识--API网关 2.Spring Cloud Gateway 详细概述 3.Spring ...

  5. gateway路由网关,zuul的替代品

    zuul1 low, zuul2 还没长大呢,不敢用. gateway 基于netty, spring flux, reactor 异步非阻塞, 快呀. 与spring良好整合, spring社区的呢 ...

  6. Spring Cloud入门-Gateway服务网关(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 Gateway 简介 相关概念 创建 api-gateway模块 在pom.xml中添加相关依赖 两种不同的配置路由方式 使用yml配置 使用Ja ...

  7. 微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关

    微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关 1. 微服务简介 1.1 服务架构演变 1.2 SpringCloud ...

  8. Gateway服务网关使用教程

    目录 1.为什么需要网关 2.gateway快速入门 1)创建gateway服务,引入依赖 2)编写启动类 3)编写基础配置和路由规则 4)重启测试 5)网关路由的流程图 3.断言工厂 4.过滤器工厂 ...

  9. 【Spring Cloud Alibaba】Gateway 服务网关

    [Spring Cloud Alibaba]Gateway 服务网关 1 架构图 2 Predicate 断言 3 路由 3.1 静态路由 3.2 动态路由 3.3 Nacos 配置 4 过滤器 4. ...

  10. 微服务01SpringCloud Eureka Ribbon Nacos Feign Gateway服务网关

    微服务技术栈导学 SpringCloud01 1.认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构.这些架构之间有怎样的差别呢? 1.0.学 ...

最新文章

  1. R语言数据描述性统计(Descriptive statistics)实战:数据全局描述信息、数值数据的描述性统计(Numerical data)、离散型数据的描述性统计(Categorical)
  2. 剑指offer18.删除链表结点(添加dummy,next域结点指向head)
  3. 用飞桨做自然语言处理:神经网络语言模型应用实例
  4. springMVC图片的上传与下载
  5. 不清楚 spring 的这几个知识点,面试直接挂了!
  6. spring boot整合JPA实现多条件查询并分页
  7. boost::geometry::strategy::vincenty用法的测试程序
  8. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
  9. pythonasyncio并发编程实战_python异步编程之asyncio(百万并发)
  10. 矩阵范数的等价性(原创)
  11. 银河麒麟桌面操作系统中获取硬盘序列号
  12. 一个优秀的网站首页是如何设计的?
  13. 航空研发软件移机时使用符号连接节省Windows系统C盘空间占用
  14. oracle 查询ddl记录,Oracle记录用户DDL操作脚本
  15. js:两种方法实现键盘按键控制
  16. 安卓性能优化之启动优化
  17. 《琅琊榜》里祁王为何必须死?
  18. Java二维码图片处理
  19. 我来回答人生百问^_^老姚
  20. sublime的一些使用技巧

热门文章

  1. css样式 向下补白,div+css[3]:css中边框border与补白padding属性设置
  2. 第二章 关系映射详解
  3. LeetCode——1888. 使二进制字符串字符交替的最少反转次数(Minimum Number of Flips to Make the Binary ...)[中等]——分析及代码(Java)
  4. 数学建模及数据分析上的插值处理——第三部分实践插值实战
  5. 宇视摄像头默认密码是多少
  6. ln x的matlab表示,ln在matlab中怎么表示
  7. 加入购物车里面的商品被商家调整价格以后如何处理金额问题
  8. 重要公告|Moonriver成功续约Kusama平行链插槽租赁期
  9. 华为鸿蒙型号,华为鸿蒙2.0正式版系统来了!可升级名单公布!你的机型在么?...
  10. Android传感器、语音识别、定位系统、Google Map API、快捷方式、widget编程总结及示例