1.Gateway简介

2.为什么有了zuul,咱们还要用Gateway

3.Gateway的三大外围概念

4.Gateway工作流程

5.Gateway的简略配置

6.Gateway通过微服务名实现动静路由

7.Gateway的Predicate

8.Gateway的Filter

1.Gateway简介
在理解gateway之前,咱们能够先登录官网看一下gateway是一个什么样的工具:https://docs.spring.io/spring...。

SpringCloud Gateway 是 Spring Cloud 的一个全新我的项目,它旨在为微服务架构提供一种简略无效对立api路由治理形式

SpringCloud Gateway 作为springCloud生态系统中的网关,指标是代替zuul,在Spring Cloud2.0以上的版本中,没有对新版本Zuul 2.0以上最高性能版本进行集成,依然还是应用的Zuul 1.x非Reactor模式的老版本。而为了晋升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则应用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway的指标提供对立的路由形式且基于 Filter 链的形式提供了网关根本的性能,例如:平安,监控/指标,和限流。

说了这么多,咱们可能还是不明确,咱们再把下面的话精简一下:

Spring Cloud Gateway 是一款网关的工具。在以前的spring Cloud版本中,采纳的都是zuul网关,然而2.x版本中,zuul的降级始终没有落实到位,spring Cloud最初本人研发了一个Spring cloud gateway代替zuul。

Spring Cloud Gateway的作用:
像反向代理,权限鉴定,流量管制,负载平衡,日志监控等等,它都能做到。

Spring Cloud Gateway位于咱们零碎的哪个地位?

这是官网给的图例,

咱们从这张图中能够看出,gateway的地位是一个比拟靠前的地位,起了整个零碎的流量入口的作用,然而理论生产中,咱们不止一个网关,也是集群模式的,所以就有了上面这张图:

2.为什么有了zuul,咱们还要用Gateway

起因一zuul公布太慢,Netflix的相干组件都进入了保护期,综合思考,还是本人开发一个Gateway是一个很现实的抉择。

起因二:Spring Cloud Gateway具备以下个性
2.1.1)动静路由:能匹配任何申请属性
2.1.2)集成Hystrix的断路器性能
2.1.3)集成 Spring Cloud 服务发现性能
2.1.4)有 Predicate(断言)和 Filter(过滤器)性能,极易编写
2.1.5)申请限流性能
2.1.6)反对门路重写

起因三:SpringCloud Gateway 与 Zuul的区别。

spring Cloud以前的网关是zuul

2.2.1)zuul 1.x是一个基于阻塞I/O的api gateway

2.2.2)Zuul 1.x基于servlet2.5应用阻塞架构,所以它不反对任何长链接,每次I/O操作都是从工作线程中抉择一个执行,申请线程被阻塞到工作线程实现,而且底层是java实现,jvm有那种第一次加载较慢的状况,所以zuul性能不佳

2.2.3)zuul 2.x理念更先进,想基于Netty非阻塞和反对长链接,但Spring Cloud目前本人做了一个Gateway,所以还没有整合

2.2.4)Spring Cloud Gateway 还反对 WebSocket, 并且与Spring严密集成领有更好的开发体验

咱们看一下zuul 1.x模型的特点
在晚期的zuul版本中,采纳的是tomcat容器,也就是传统的servlet IO模型
咱们来温习一下servlet的生命周期
servlet由servlet容器进行生命周期的治理。
容器启动的时候,会结构servlet对象并调用servlet的init()进行初始化。
容器运行的时候,承受申请,为每个申请调配一个线程(从线程池中获取闲暇线程),而后调用service()。
容器敞开的时候,调用servlet destory()销毁servlet。

上述模式的毛病:
servlet是一个简略的网络IO模型,当申请进入servlet容器的时候,servlet容器就会为其绑定一个线程,在并发不高的状况下,这种模型是实用的,然而一旦并发量进步,线程数量就会上涨,而线程资源的代码比拟低廉(上下文切换,内存耗费),重大影响申请的解决工夫。在一些简略的业务场景下,不心愿为每个request调配线程,只须要1个或者几个线程就能对应极大并发的申请,这种场景下servlet的模型就没有劣势。

所以zuul 1.x是基于servlet之上的一个阻塞式处理器,spring实现了解决所有request申请的一个servlet(DispatcherServlet)并由该阻塞式处理器解决,所以springcloud zuul无奈解脱servlet模型的弊病。

接下来咱们来看看GateWay模型

新的gateway模型采纳了spring WebFlux的模型, https://docs.spring.io/spring...

传统的框架,如spring mvc,struts2,都是基于servlet api和servlet容器之上运行的。

然而servlet3.1之后有了异步非阻塞的反对,而webFlux是一个典型的非阻塞异步的框架,它应用了一个非阻塞的web堆栈来解决大量线程的并发性并以更少的硬件资源进行扩大

3.Gateway的三大外围概念
3.1)Route(路由)
路由是构建网关的根本模块,由id,指标uri,一系列的断言和过滤器组成,就相当于把一个拜访门路转发到另外一个拜访门路,其中蕴含了一系列规定,如果断言为true则匹配该路由。

3.2)Predicate(断言)
匹配HTTP申请中的所有内容,如果申请与断言相匹配,则进行路由。

3.3)Filter(过滤)
应用过滤器,能够在申请在路由之前或者之后进行批改。

通过这张流程图能够看出,当一个web申请进来后,通过predicate匹配条件,就能够定位到真正的服务节点同时在转发过程的前后,通过filter进行一些精细化管制。

4.Gateway工作流程

咱们看看官网是如何介绍它的工作流程的:

客户端向Spring Cloud Gateway发出请求,如果网关处理器匹配到了路由就将申请发送到网关处理程序。处理器再通过该申请指定的过滤器链,将申请发送给理论服务,让服务执行业务逻辑,而后返回。

过滤器之间用需先离开是因为咱们能够在发送申请之前和之后运行逻辑。

在pre能够用来做参数校验,权限校验,流量监控,日志输入等等
在post能够用来做相应内容,响应头的批改,日志的输入,流量监控等等。

5.Gateway的简略配置
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.2.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.example</groupId>    <artifactId>cloud-gateway-9000</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>cloud-gateway-9000</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>1.8</java.version>        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-gateway</artifactId>        </dependency>        <!-- gateway要排除这个依赖,因为 gateway曾经自带了spring-boot-starter-web-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>            <exclusions>                <exclusion>                    <groupId>*</groupId>                    <artifactId>*</artifactId>                </exclusion>            </exclusions>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-actuator</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>${spring-cloud.version}</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

yml:

server:  port: 9000eureka:  instance:    hostname: cloud-gateway #eureka服务端的实例名称    prefer-ip-address: true #拜访门路能够显示IP地址    instance-id: ${spring.cloud.client.ip-address}:${server.port}-cloud-gateway #拜访门路的名称格局  client:    register-with-eureka: true     #false示意不向注册核心注册本人。    fetch-registry: true     #false示意本人端就是注册核心,我的职责就是保护服务实例,并不需要去检索服务    service-url:      #集群指向其它eureka      defaultZone: http://127.0.0.1:8001/eureka/,http://127.0.0.1:8002/eureka/spring:  application:    name: cloud-gateway  cloud:    gateway:      routes:        - id: routh1 #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名          uri: http://localhost:8501          #匹配后提供服务的路由地址          predicates:            - Path=/payment/get/**         # 断言,门路相匹配的进行路由

而后,咱们通过网关拜访接口,就能够转发过来了:http://localhost:9000/payment...

6.Gateway通过微服务名实现动静路由

咱们下面只是把一个接口固定转发给另外一个服务而已,然而服务的端口可能是变动的而且还是集群部署,须要负载平衡的,咱们不可能把服务名加端口号写死,更不可能只转发到一个服务提供者,所以咱们须要通过微服务名称调用+负载平衡:

pom:

spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true #开启从注册核心动态创建路由的性能,利用微服务名进行路由      routes:        - id: routh1 #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名          #uri: http://localhost:8501          #匹配后提供服务的路由地址          uri: lb://service-provider #匹配后提供服务的路由地址          predicates:            - Path=/payment/get/**         # 断言,门路相匹配的进行路由

7.Gateway的Predicate

上述predicates只是用来做一个uri地址的匹配和转移,其实predicates还有许多的作用,Spring Cloud Gateway蕴含许多内置的Route Predicate工厂。这些Predicate都与HTTP申请的不同属性匹配,比方有以下这些匹配形式:
工夫匹配(某个工夫点前/后/区间才凋谢这个转发)

- id: routh #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://service-provider #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,门路相匹配的进行路由- After=2022-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 这个工夫之后再凋谢转发- Before=2022-02-05T15:10:03.685+08:00[Asia/Shanghai]         # 这个工夫之前凋谢转发- Between=2022-02-02T17:45:06.206+08:00[Asia/Shanghai],2022-03-25T18:59:06.206+08:00[Asia/Shanghai] # 这个工夫区间凋谢转发

cookie(cookie肯定要带某个参数)

- id: routh #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://service-provider #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,门路相匹配的进行路由- Cookie=username,slf

Header匹配(申请头参数匹配)

- id: routh #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://service-provider #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,门路相匹配的进行路由- Header=X-Request-Id, \d+  # 申请头要有X-Request-Id属性并且值为整数的正则表达式

申请形式匹配(Get,POST等等)

- id: routh #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名# uri: http://localhost:8001          #匹配后提供服务的路由地址uri: lb://service-provider #匹配后提供服务的路由地址predicates:- Path=/payment/get/**         # 断言,门路相匹配的进行路由- Method=GET

详情更多能够看官网:https://cloud.spring.io/sprin...

说白了,Predicate就是为了实现一组匹配规定,让申请过去找到对应的Route进行解决。

8.Gateway的Filter

咱们看完上述的配置,然而还是发现一个毛病,难不成咱们每个接口都要去配置一遍转发的接口吗?

这个时候,咱们就能够应用Filter————过滤器!

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

server:  port: 9000eureka:  instance:    hostname: cloud-gateway #eureka服务端的实例名称    prefer-ip-address: true #拜访门路能够显示IP地址    instance-id: ${spring.cloud.client.ip-address}:${server.port}-cloud-gateway #拜访门路的名称格局  client:    register-with-eureka: true     #false示意不向注册核心注册本人。    fetch-registry: true     #false示意本人端就是注册核心,我的职责就是保护服务实例,并不需要去检索服务    service-url:      #集群指向其它eureka      defaultZone: http://127.0.0.1:8001/eureka/,http://127.0.0.1:8002/eureka/spring:  application:    name: cloud-gateway  cloud:    gateway:      discovery:        locator:          enabled: true #开启从注册核心动态创建路由的性能,利用微服务名进行路由      routes:        - id: routh1 #payment_route    #路由的ID,没有固定规定但要求惟一,倡议配合服务名          #uri: http://localhost:8501          #匹配后提供服务的路由地址          uri: lb://service-provider/** #匹配后提供服务的路由地址          predicates:            - Path=/gateway/service-provider/**         # 断言,门路相匹配的进行路由,咱们能够通过服务名称来指定接口,这个服务的接口全副转到这个服务的接口上面,并且去掉两个参数          filters:            - StripPrefix=2  # 去掉path的/gateway/service-provider,将尾巴局部接到url上,StripPrefix=几 就是去掉几个参数

更多过滤器请看:https://cloud.spring.io/sprin...