Spring Cloud Gateway(网关)

概念

Gateway是基于异步非阻塞模型上进行开发的,有springcloud团队开发。用来代替Zuul。

内容

Route(路由)

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

Predicate(断言)

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

Filter(过滤)

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

Zuul

Zuul1基于servlet阻塞I/O的API Gateway,且进入维护
Zuul2虽然基于非阻塞I/O,但是还没有发布,且SpringCloud没有整合

优点

  1. 基于Spring Framework5, Project Reactor 和SpringBoot 2.0 进行构建
  2. 动态路由:能够匹配任何请求属性
  3. 可以对路由指定Predicate(断言) 和 Filter(过滤器)
  4. 继承Hystrix的断路器功能
  5. 集成SpringCloud服务发现功能
  6. 易于编写的Predicate(断言) 和 Filter(过滤器)
  7. 请求限流功能
  8. 支持路由重写

作用

可以不对外开放服务端,只对外开放网关

Spring Cloud Gateway工作流程

Spring Cloud Gateway工作流程.png

使用

  1. 新建网关模型
  2. pom引入Gateway
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  1. 将网关注册进eureka/Zookeeper/Consul
  2. 由yml网关配置。在yml中加入
spring: 
  cloud:
    gateway:
      routes:
        - id: payment_routh #路由的id,没有固定规则但要求唯一,建议配合服务名
        -url: http://localhost:8001 #匹配后提供服务的路由地址
        -predicates:
          - Path=/payment/get/** #断言,路径相匹配的进行路由

        - id: payment_routh2 #路由的id,没有固定规则但要求唯一,建议配合服务名
        -url: http://localhost:8001 #匹配后提供服务的路由地址
        -predicates:
          - Path=/payment/1b/** #断言,路径相匹配的进行路由
  1. 测试
    在网关中,不需要springboot的web和actuator,否则启动报错。在pom中移除即可
    --启动eureka/Zookeeper/Consul、网关、服务端
    --通过网关访问服务端
  2. 用代码配置,创建一个配置类
@Configuration
public class GatwayConfig{
  @Bean
  public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
    RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
    
    routes .route("path_route",r -> r.path("/guonei").uri("http://baidu.com/guonei")).build();
    return routes.build();
  }
}

实现动态路由功能

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

实现

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

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

predicates的参数.如下为官网内容

  1. 所述After路线谓词工厂有一个参数,一个datetime(其是Java ZonedDateTime)。该谓词匹配在指定日期时间之后发生的请求。下面的示例配置路由后谓词:
    例子1. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

这条路线符合2017年1月20日17:42山区时间(丹佛)之后的任何请求。

  • 获取时区
ZonedDateTime zbj = ZonedDateTime.now();//默认时区
System.out.println(zbj);
  1. 所述Before路线谓词工厂有一个参数,一个datetime(其是Java ZonedDateTime)。该谓词匹配在指定之前发生的请求datetime。下面的示例配置路由前谓词:
    例子2. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

这条路线符合2017年1月20日山区时间(丹佛)之前的任何请求。

  1. 该Between路线谓词工厂有两个参数,datetime1并且datetime2 这是JavaZonedDateTime对象。该谓词匹配之后datetime1和之前发生的请求datetime2。该datetime2参数必须是后datetime1。以下示例配置了路由之间的谓词:
    例子3. application.yml
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]

此路线与2017年1月20日山区时间(丹佛)之后和2017年1月21日17:42山区时间(丹佛)之后的任何请求相匹配。这对于维护时段可能很有用。

  1. 所述Cookie路线谓词工厂采用两个参数,该cookiename和regexp(其是Java正则表达式)。该谓词匹配具有给定名称且其值与正则表达式匹配的cookie。以下示例配置cookie路由谓词工厂:
    例子4. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

此路由匹配具有名称为chocolate与ch.p正则表达式匹配的cookie的请求。

  1. 所述Header路线谓词工厂采用两个参数,报头name和一个regexp(其是Java正则表达式)。该谓词与具有给定名称的标头匹配,该标头的值与正则表达式匹配。以下示例配置标头路由谓词:
    例子5. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

如果请求具有名为X-Request-Id其值与\d+正则表达式匹配的标头(即,其值为一个或多个数字),则此路由匹配。

  1. Host路线谓词工厂需要一个参数:主机名的列表patterns。该模式是带有.分隔符的Ant样式的模式。谓词与Host匹配模式的标头匹配。以下示例配置主机路由谓词:
    例子6. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

{sub}.myhost.org还支持URI模板变量(例如)。

如果请求具有这种路由匹配Host用的头值www.somehost.orgbeta.somehost.orgwww.anotherhost.org

该谓词提取URI模板变量(例如sub,在前面的示例中定义的)作为名称和值的映射,并ServerWebExchange.getAttributes()使用中定义的键将其放在中ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。这些值可供工厂使用GatewayFilter

  1. 所述Method路线谓词厂需要methods的参数,它是一个或多个参数:HTTP方法来匹配。以下示例配置方法route谓词:
    例子7. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

如果请求方法是aGET或a,则此路由匹配POST。

  1. Path路线谓词厂有两个参数:春天的列表PathMatcher patterns和所谓的可选标志matchTrailingSlash(默认true)。以下示例配置路径路由谓词:
    例子8. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}

如果请求路径为,则此路由匹配,例如:/red/1/red/1//red/blue/blue/green

如果matchTrailingSlash设置为false,则请求路径/red/1/将不匹配。

该谓词提取URI模板变量(例如segment,在前面的示例中定义的)作为名称和值的映射,并ServerWebExchange.getAttributes()使用中定义的键将其放在中ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE。这些值可供工厂使用GatewayFilter

可以使用实用程序方法(称为get)来简化对这些变量的访问。下面的示例演示如何使用该get方法:

Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);

String segment = uriVariables.get("segment");
  1. 所述Query路线谓词工厂采用两个参数:所要求的param和可选的regexp(其是Java正则表达式)。以下示例配置查询路由谓词:
    例子9. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green

如果请求包含green查询参数,则前面的路由匹配。

application.yml

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

如果请求包含一个前述路线匹配red,其值相匹配的查询参数gree.的regexp,所以green和greet将匹配。

  1. 所述RemoteAddr路线谓词工厂需要的列表(分钟尺寸1) sources,其是CIDR的表示法(IPv4或IPv6)的字符串,如192.168.0.1/16(其中192.168.0.1是一个IP地址和16一个子网掩码)。以下示例配置一个RemoteAddr路由谓词:
    例子10. application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

如果请求的远程地址为,则此路由匹配192.168.1.10。

  1. Weight路线谓词工厂有两个参数:groupweight(一个int)。权重是按组计算的。以下示例配置权重路由谓词:
    例子11. application.yml
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。

Spring Cloud gateway的Filter

非自定义的简单,按照文档配置即可
Spring Cloud gateway的Filte官方文档

生命周期与种类

  1. 生命周期-Only Two
  • pre
  • post
  1. 种类 - Only Two
  • GatewayFilter 单一的Filter
  • GlobalFilter 全局的Filter

自定义过滤器

  1. 新建Gateway配置类,实现GlobalFilter,Ordered接口,内容如下
@Component
public class GatewayConfig implements GlobalFilter,Ordered{
  @Override
  public Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//exchange可以获取到请求信息,chain用来将新的请求发出到下一个过滤链
    String name = exchange.getRequest().getQueryParams().getFilter("uname");
    if(name == null){
      ...
    }
    return chain.filter(exchange);
  }
  //getOrder是顺序
  @Override
  public int getOrder(){
    ...
    return 0;
  }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容