Gateway

概述

1、这个项目提供了一个建立在 Spring 生态系统之上的 API 网关,包括 Spring 5、Spring Boot 2、Project Reactor

2、Spring Cloud Gateway 旨在提供一种简单而有效的方式对 API 进行路由,并为其提供横切关注点,如:安全、监控 / 指标、限流

3、作用:反向代理、鉴权、流量控制、熔断、日志监控等

 

三大核心概念

1、Route

(1)路由:构建网关的基本模块

(2)组成:ID、目标 URI、一系列断言 + 过滤器

(3)断言为 true,则匹配该路由

2、Predicate

(1)断言:参考 java.util.function.Predicate

(2)匹配 HTTP 请求中的所有内容,如:请求头、请求参数,若请求与断言匹配,则进行路由

3、Filter

(1)过滤器:Spring 框架中 GatewayFilter 实例

(2)使用过滤器,可以在请求被路由之前或之后,对请求进行修改

 

工作流程

1、客户端向 Spring Cloud Gateway 发出请求

(1)如果 Gateway Handler Mapping 确定一个请求与路由相匹配,它将被发送到 Gateway Web Handler

(2)Gateway Web Handler 通过一个特定于该请求的过滤器链,来将请求发送到实际服务执行业务逻辑,然后返回

(3)过滤器被虚线分割的原因:过滤器可以在代理请求发送之前和之后运行逻辑

(4)所有的“pre”过滤器逻辑都被执行,然后发出代理请求,“pre”类型的过滤器:参数校验、权限校验、流量监控、日志输出、协议转换等

(5)在代理请求发出后,“post”过滤器逻辑被运行,“post”类型的过滤器:修改响应内容、修改响应头、输出日志、流量监控等

2、在路由中定义的没有端口的 URI,其 HTTP 和 HTTPS URI 的默认端口值分别为 80 和 443

3、Handler 再通过指定的过滤器链

 

核心依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

 

配置方式(示例)

1、yaml 配置(建议)

(1)访问地址:http://localhost:9001/payment/get/**

(2)路由地址:http://localhost:8001/payment/get/**

server:
  port: 9001

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

2、配置类 Bean(示例)

(1)访问地址:http://localhost:9001/payment

(2)路由地址:http://localhost:8001/payment

server:
  port: 9001
@Configuration
public class GateWayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        routes.route(
            //路由ID
            "payment",
            //断言,路径相匹配的进行路由:- Path = 
            r -> r.path("/payment")
            //匹配后提供服务的路由地址
            .uri("http://localhost:8001/payment")).build();
        return routes.build();
    }
}

 

动态路由

1、默认情况下,Gateway 根据注册中心的服务列表,以注册中心上的微服务名称为路径,创建动态路由进行转发

2、yaml 配置

(1)访问地址:http://localhost:9001/payment/get

(2)lb://serviceName 是 Spring Cloud Gateway 在微服务中自动创建的负载均衡 uri

(3)lb 为 uri 协议,表示启用 Gateway 负载均衡

(4)Gateway 在注册中心查找 serviceName 的微服务,进行负载均衡转发

server:
  port: 9001

spring:
  cloud:
    gateway:
      discovery:
        locator:
          #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          enabled: true
      routes:
        #路由ID,没有固定规则,但要求唯一,建议配合服务名
        - id: payment
          #匹配后提供服务的路由地址,lb为uri协议,表示启用Gateway负载均衡
          uri: lb://cloud-payment-service
          predicates:
            #断言,路径相匹配的进行路由
            - Path=/payment/get/**

 

Route Predicate Factories

1、路由断言工厂

(1)Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础设施的一部分

(2)Spring Cloud Gateway 包括许多内置的路由断言工厂,所有这些断言都与 HTTP 请求的不同属性相匹配,可以用逻辑和语句组合多个路由断言工厂

2、The After Route Predicate Factory

(1)接受一个参数,即 datetime(java.time.ZonedDateTime)

(2)这个断言匹配发生在指定日期时间之后的请求

(3)例:该路由与山区时间(丹佛)2017 年 1 月 20 日 17:42 之后提出的任何请求相匹配

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

3、The Before Route Predicate Factory

(1)接收一个参数,即 datetime(java.time.ZonedDateTime)

(2)这个断言匹配发生在指定日期时间之前的请求

(3)例:该路由与山区时间(丹佛)2017 年 1 月 20 日 17:42 之前提出的任何请求相匹配

spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

4、The Between route predicate factory

(1)需要两个参数,datetime1 和 datetime2,它们是 java.time.ZonedDateTime 对象

(2)这个断言匹配发生在 datetime1 之后和 datetime2 之前的请求

(3)例:这个路由与 2017 年 1 月 20 日山区时间(丹佛)17:42 之后和 2017 年 1 月 21 日山区时间(丹佛)17:42 之前的任何请求相匹配,这对维护窗口可能是有用的

spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: https://example.org
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

5、The Cookie Route Predicate Factory

(1)接受两个参数,即 cookie name 和一个 regexp(Java 正则表达式)

(2)这个断言匹配具有给定名称,且其值符合正则表达式的 cookie

(3)例:这个路由匹配有一个名为 chocolate 的 cookie 的请求,其值符合 ch.p 正则表达式

spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

6、The Header Route Predicate Factory

(1)需要两个参数,header 和一个 regexp(Java 正则表达式)

(2)这个谓词与具有给定名称且其值与正则表达式相匹配的头匹配

(3)例:如果请求有一个名为 X-Request-Id 的头,其值与 \d+ 正则表达式相匹配(即它有一个或多个数字的值),则该路由匹配

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

7、The Host Route Predicate Factory

(1)接受一个参数:一个主机名称模式的列表。该模式是 Ant 风格的模式,以 . 为分隔符

(2)这个断言匹配符合该模式的 Host 头

(3)例:如果请求的 Host 头的值为 www.somehost.org 或 beta.somehost.org 或 www.anotherhost.org,则该路由匹配

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

8、The Method Route Predicate Factory

(1)接受一个 methods 参数,它是一个或多个参数:要匹配的 HTTP 方法

(2)例:如果请求方式是 GET 或 POST,则该路由匹配

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

9、The Path Route Predicate Factory

(1)需要两个参数:一个 Spring PathMatcher 模式的列表、一个可选的标志 matchTrailingSlash(默认为 true)

(2)例:如果请求路径是,例如:/red/1 或 /red/1/ 或 /red/blue 或 /blue/green,该路由匹配

(3)如果 matchTrailingSlash 被设置为 false,那么请求路径 /red/1/ 将不会被匹配

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}

10、The Query route predicate factory

(1)需要两个参数:一个必需的 param、一个可选的 regexp(Java 正则表达式)

(2)例:如果请求中包含一个 red 的查询参数,其值与 gree.regexp 相匹配,那么前面的路由就会匹配,所以 green 和 greet 会匹配

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.

11、The RemoteAddr route predicate factory

(1)接受一个 sources 列表(最小尺寸为 1),它是 CIDR-notation(IPv4 或 IPv6)字符串,如:192.168.0.1/16(其中 192.168.0.1 是一个 IP 地址,16 是一个子网掩码)

(2)例:如果请求的远程地址是,例如:192.168.1.10,则该路由匹配

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

12、The Weight route predicate factory

(1)需要两个参数:group 和 weight(int)

(2)权重是按组计算的

(3)例:该路由将转发 ~80% 的流量到 weighthigh.org,~20% 的流量到 weightlow.org

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

13、The XForwarded Remote Addr route predicate factory

(1)接受一个 sources 列表(最小尺寸为 1),这些来源是 CIDR-notation(IPv4 或 IPv6)字符串,如:192.168.0.1/16(其中 192.168.0.1 是一个 IP 地址,16 是子网掩码)

(2)这个路由断言允许根据 X-Forwarded-For HTTP 头对请求进行过滤

(3)这可以与反向代理一起使用,如:负载均衡器或网络应用程序防火墙,只有当请求来自这些反向代理所使用的受信任的 IP 地址列表时,才应该被允许

(4)例:如果 X-Forwarded-For 头包含,例如:192.168.1.10,则该路由匹配

spring:
  cloud:
    gateway:
      routes:
      - id: xforwarded_remoteaddr_route
        uri: https://example.org
        predicates:
        - XForwardedRemoteAddr=192.168.1.1/24

 

GatewayFilter Factories

1、路由过滤器

(1)允许以某种方式修改传入的 HTTP 请求或传出的 HTTP 响应

(2)路由过滤器的范围是一个特定的路由

(3)Spring Cloud Gateway 包括许多内置的 GatewayFilter Factory,产生路由过滤器

2、生命周期

(1)pre:请求被执行前调用

(2)post:请求被执行后调用

3、种类

(1)GatewayFilter

(2)GlobalFilter

4、自定义全局过滤器(开发常用)

 

(1)当一个请求与路由匹配时,过滤网络处理器将 GlobalFilter 的所有实例和 GatewayFilter 的所有路由特定实例添加到一个过滤链中

(2)这个组合的过滤链由 org.springframework.core.Ordered 接口进行排序,可以通过实现 getOrder() 方法来设置这个接口,数字越小,优先级又高

(3)由于 Spring Cloud Gateway 区分过滤器逻辑执行的“pre”和“post”阶段,优先级最高的过滤器在“pre”阶段是第一个,在“host”阶段是最后一个

@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    //ServerWebExchange:HTTP请求-响应交互的契约。提供对HTTP请求和响应的访问,也暴露了额外的服务器端处理相关的属性和功能,如:请求属性
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        //将ServerWebExchange通过过滤链传递到下一个过滤器
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}
posted @   半条咸鱼  阅读(211)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示