Spring Cloud Gateway入门

Spring Cloud Gateway

官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

Spring Cloud中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中,zuul的升级一直跳票,迟迟不发布版本,SpringCloud最后自己研发了一个网关替代Zuul,那就是Spring Cloud Gateway

Spring Cloud Gateway 是 Spring Cloud 的一个全新子项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor是一个运行在JVM上的反应式编程基础库 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

spring Cloud Gateway 特性

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

Spring Cloud Gateway的核心概念

  • Route 路由,它是网关的基础元素,包含ID、目标URI、断言、过滤器组成,当前请求到达网关

时,会通过Gateway Handler Mapping,基于断言进行路由匹配,当断言为true时,匹配到路由

进行转发

  • Predicate,断言,java8的一个函数,它可以允许开发人员去匹配HTTP请求中

的元素,一旦匹配为true,则表示匹配到合适的路由进行转发

  • Filter,过滤器,可以在请求发出的前后进行一些业务上的处理,比如授权、限流等。

它的整体工作原理如下。

其中,predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元

素,再加上目标uri,就可以实现一个具体的路由了。

客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发

送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。

过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。 pre 前置过滤器逻辑先

执行,然后执行代理请求;代理请求完成后,执行 post 后置过滤器逻辑

流程图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
在这里插入图片描述

构建项目

Spring Cloud Gateway 网关路由配置方式:

  • 在配置文件 yml 中配置

    引入依赖包

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

Spring Cloud Gateway 是使用 netty+webflux 实现因此不需要再引入 web 模块。

我们先来测试一个最简单的请求转发。

server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
        - predicates:      #-横线表示数组可以配置多个
            - Path=/gateway/**   #匹配gateway的请求
          filters:               
            - StripPrefix=1      #请求跳过gateway 
          uri: http://localhost:8081/

访问请求 http://localhost:8080/gateway/config

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

可以看到已经转发成功了

断言部分 可以查看spring官网

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-after-route-predicate-factory

1.The After Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]  在这个时间之后匹配路由

2.The Before Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]  在这个时间之前匹配路由

3.The Between Route Predicate Factory

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]   在这2个时间的过程进行匹配路由

4.The Cookie Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
        - id: config_route   #-横线表示数组可以配置多个
          predicates:
            - Path=/gateway/**   #匹配gateway的请求
          filters:
            - StripPrefix=1      #请求跳过gateway
          uri: http://localhost:8081/
        - id: cookie_route
          predicates:
            - Cookie=name,mic
          uri: https://baidu.com    根据cookie匹配对应的路由信息 key value格式

5.The Header Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+  根据http协议中携带的header信息进行路由

6.The Host Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org  根据host匹配对应的路由

7.The Method Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST    根据请求方式匹配路由

8.The Path Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}  根据路径匹配对应的路由信息

9.The Query Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green   根据查询条件匹配对应的路由

10.The RemoteAddr Route Predicate Factory

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24  根据ip地址匹配对应的路由

11.The Weight Route Predicate Factory

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  

12.The XForwarded Remote Addr Route Predicate Factory

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

访问http://localhost:8080

请求中加一个cookie信息

可以看到下面的信息已经转发到一个html登录界面
在这里插入图片描述

下面来看看springCloud中cookie是怎么实现的

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.cloud.gateway.handler.predicate;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import javax.validation.constraints.NotEmpty;
import org.springframework.http.HttpCookie;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

public class CookieRoutePredicateFactory extends AbstractRoutePredicateFactory<CookieRoutePredicateFactory.Config> {
    public static final String NAME_KEY = "name";
    public static final String REGEXP_KEY = "regexp"; 

    public CookieRoutePredicateFactory() {
        super(CookieRoutePredicateFactory.Config.class);
    }

    public List<String> shortcutFieldOrder() {
        return Arrays.asList("name", "regexp");  //配置文件中的字段映射可配置多个
    }

    public Predicate<ServerWebExchange> apply(CookieRoutePredicateFactory.Config config) {
        return new GatewayPredicate() { //Predicate  java8中的一个函数接口中的test方法返回一个true/false的boolean
            public boolean test(ServerWebExchange exchange) {
                List<HttpCookie> cookies = (List)exchange.getRequest().getCookies().get(config.name); //获得配置文件中的参数
                if (cookies == null) {
                    return false;
                } else {
                    Iterator var3 = cookies.iterator();

                    HttpCookie cookie;
                    do {
                        if (!var3.hasNext()) {
                            return false;
                        }

                        cookie = (HttpCookie)var3.next();
                    } while(!cookie.getValue().matches(config.regexp));

                    return true;
                }
            }

            public Object getConfig() {
                return config;
            }

            public String toString() {
                return String.format("Cookie: name=%s regexp=%s", config.name, config.regexp);
            }
        };
    }

    @Validated
    public static class Config {
        @NotEmpty
        private String name;
        @NotEmpty
        private String regexp;//正则表达式匹配

        public Config() {
        }

        public String getName() {
            return this.name;
        }

        public CookieRoutePredicateFactory.Config setName(String name) {
            this.name = name;
            return this;
        }

        public String getRegexp() {
            return this.regexp;
        }

        public CookieRoutePredicateFactory.Config setRegexp(String regexp) {
            this.regexp = regexp;
            return this;
        }
    }
}

  • 自定义实现AuthRoutePredicateFactory

Auth的后缀必须是RoutePredicateFactory 这样 因为springcloudGateway 会进行筛选Predicate为Authn的key进行截取

如果实现自定义的实现必须按照这个格式来

package com.example.springcloudgateway8080;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;


@Component
public class AuthRoutePredicateFactory extends AbstractRoutePredicateFactory<AuthRoutePredicateFactory.Config> {


    public AuthRoutePredicateFactory() {
        super(Config.class);
    }

    private static final String NAME_KEY="name";
    private static final String VALUE_KEY="value";


    @Override
    public List<String> shortcutFieldOrder() {//快捷配置多个参数
        return Arrays.asList(NAME_KEY,VALUE_KEY);//name和value就是配置文件中的参数
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        //Header中携带了某个值,进行header的判断
        return (exchange->{
            HttpHeaders headers=exchange.getRequest().getHeaders();
            List<String> headerList=headers.get(config.getName());
            return headerList.size()>0;
        });
    }

    public static class Config {

        private String name;
        private String value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}

配置文件

server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
        - id: config_route   #-横线表示数组可以配置多个
          predicates:
            - Path=/gateway/**   #匹配gateway的请求
          filters:
            - StripPrefix=1      #请求跳过gateway
          uri: http://localhost:8081/
        - id: cookie_route
          predicates:
            #- Cookie=name,mic
            - Path=/define/**
            - Auth=Authorization,token
          uri: https://baidu.com

访问:http://localhost:8080/define

server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: config_route #-横线表示数组可以配置多个
predicates:
- Path=/gateway/** #匹配gateway的请求
filters:
- StripPrefix=1 #请求跳过gateway
uri: http://localhost:8081/
- id: cookie_route
predicates:
#- Cookie=name,mic
- Path=/define/**
- Auth=Authorization,token
uri: https://www.baidu.com


访问:http://localhost:8080/define

 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值