SpringCloud Gateway网关

SpringCloud Gateway网关
在提供一种简单而有效的方式来路由到API,提供例如:安全性,监控指标等功能。

官方说明文档

//官方
https://spring.io/projects/spring-cloud-gateway#overview
//官方说明文档
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/index.html#gateway-starter
image.png
image.png

Spring Cloud Gateway的工作方式:

官网截图.png

三个重要部分

Route路由

网关的基本构建单元。它由ID,URI,匹配规则集合和过滤集合定义。

Predicate 判定器

判断请求走哪条路由规则。匹配来自HTTP请求的如何内容,例如标头或者参数。

Filter 过滤器

用于在发送下游请求之前或之后修改请求和响应

内置路由选择器

Route Predicate Factories

路由选择器 描述
After 匹配在指定日期之后发生的请求
Before 匹配在指定日期时间之前发生的请求
Between 匹配在指定日期时间之间发生的请求
Cookie 匹配具有指定Cookie值的请求
Header 匹配header中具有指定名称且值与正则表达式匹配的请求
Host 匹配指定的host
Method 匹配指定的method
Path 匹配指定的请求路径
Query 匹配指定的查询参数
RemoteAddr 匹配指定的客户端ip
image.png

内置过滤器

GatewayFilter Factories

过滤器类型 描述
AddRequestHeader 网关下游请求发起前,增加请求的header
AddRequestParameter 网关下游请求发起前,增加请求的参数
AddResponseHeader 网关下游响应之后,增加响应的header
Hystrix 为该路由增加熔断器
FallbackHeaders 熔断后,为响应增加一个降级的header
PrefixPath 设置发起网关下游请求的路径前缀(隐藏真实路径)
PreserveHostheader 网关发起下游请求时,是否在header中附带原请求中的host
RequestRateLimiter 网关限流器(可选择结合redis实现)
RedirectTo 将该路由的请求重定向到指定地址
RemoveNoProxyHeaders 网关发起下游请求时,删除指定header(默认删除一系列header名)
RemoveRequestHeader 网关下游请求发起前,删除指定的请求header
RemoveResponseHeader 网关下游响应之后,删除指定的响应的header
RewritePath 请求路径重写
RewriteResponseHeader 重写指定的响应header
SaveSession 网关保存session会话
SecureHeaders 为响应内容增加一系列和安全相关的header信息
SetPath 路径修改(重写类型)
SetResponseheader 替换(不是新增)指定的响应header
SetStatus 设置该路由的响应状态码
StripPrefix 网关在发起请求之前,根据/分隔删除部分url路径(eg:2,则/name/bar/foo变为/foo)
Retry 为指定路由开启错误重试机制
RequestSize 请求内容大小限制,超出大小则返回413Payload Too Large
Modify Request Body 网关修改客户端的请求内容,仅支持代码设置(实质性功能)
Modify Response Body 网关修改下游的响应内容,仅支持代码设置(实质性功能)
LoadBalancerClient 自定义路由的负载均衡(配置ribbon服务后,路由的uri修改为lb:service)(eureka无关)
Websocket 支持websocket代理(配置方式uri:ws://localhost:3001
Gateway Metrics Filter 开启路由metrics功能(spring.cloud.gateway.metrics.enabled=true默认false关闭)
default filters 要添加过滤器并将其应用于所有路由
image.png

全局过滤器

GlobalFilter

//官网示例
@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return -1;
    }
}

局部过滤器

GatewayFilter

@Configuration
public class GatewayFilterConfig {

//    /**
//     * 把过滤器注入容器
//     * @return
//     */
    @Bean
    TestGatewayFilterFactory testGatewayFilterFactory(){
        return new TestGatewayFilterFactory();
    }
}

/**
 * 局部过滤器
 * 
 */
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {

    /**
     * 定义可以再yaml中声明的属性变量
     */
    private static final String TYPE = "type";//参数
    private static final String TYPE_2 = "type_2";//参数2

    public TestGatewayFilterFactory(){
        //这里需要将自定义的config传过去,否则会报告ClassCastException
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        System.err.println("GatewayFilter config 自定义过滤器工厂,config="+config.toString());
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.err.println("GatewayFilter config 自定义过滤器工厂 filter==");
                return chain.filter(exchange);
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, TYPE_2);
    }

    //自定义的config类,用来设置传入的参数
    public static class Config{
        //Put the configuration properties for your filter here
        /**
         * 过滤类型
         */
        private String type;

        /**
         * 操作
         */
        private String type_2;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getType_2() {
            return type_2;
        }

        public void setType_2(String type_2) {
            this.type_2 = type_2;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "type='" + type + '\'' +
                    ", type_2='" + type_2 + '\'' +
                    '}';
        }
    }

}

在application.yml配置文件,配置自定义filters

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      # 路由 id
      routes:
        - id: study
          # 注册服务的名: lb://
          uri: lb://server-demo
          predicates:  #断言
            - Path=/index/**
#           - Query=paramA
           # - Before=2020-04-20T06:06:06+08:00[Asia/Shanghai]
          filters:
            - name: Test
              args:
                type: root
                type_2: 1112233333
image.png

集成示例

1 . pom导入依赖

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

    <dependencies>
      <!--gateway 包含了web-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--netflix-eureka-client注册中心客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>

配置

@Configuration
public class GatewayFilterConfig {

//    /**
//     * 把过滤器注入容器
//     * @return
//     */

    @Bean
    TestGatewayFilterFactory testGatewayFilterFactory(){
        return new TestGatewayFilterFactory();
    }

    /**
     * 全局过滤链
     * @return
     */
    @Bean
    public GlobalFilter customFilter() {
        return new CustomGlobalFilter();
    }

    /**
     * 全局拦截
     * 全局过滤器GlobalFilter
     */
    public class CustomGlobalFilter implements GlobalFilter, Ordered {

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.err.println("GlobalFilter CustomGlobalFilter ");
            return chain.filter(exchange);
        }

        /**
         * 拦截顺序
         * @return
         */
        @Override
        public int getOrder() {
            return -1;
        }
    }
}

TestGatewayFilterFactory 局部过滤器

/**
 * 局部过滤器
 *
 */
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {

    /**
     * 定义可以再yaml中声明的属性变量
     */
    private static final String TYPE = "type";//参数
    private static final String TYPE_2 = "type_2";//参数2

    public TestGatewayFilterFactory(){
        //这里需要将自定义的config传过去,否则会报告ClassCastException
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        System.err.println("GatewayFilter config 自定义过滤器工厂,config="+config.toString());
//        return new GatewayFilter() {
//            @Override
//            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//                System.err.println("GatewayFilter config 自定义过滤器工厂 filter==");
//                return chain.filter(exchange);
//            }
//        };
        return new InnerFilter(config);
    }

    
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, TYPE_2);
    }

    /**
     * 设置 执行顺序
     */
    public class InnerFilter implements GatewayFilter, Ordered {

        private Config config;

        public InnerFilter(Config config){
            this.config = config;
        }

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //按order,优先被执行,CustomGlobalFilter执行,apply(),then方法
            System.err.println("GatewayFilter config 自定义过滤器工厂 InnerFilter ,config="+this.config.toString());

            //进入下一个处理流程
//            return chain.filter(exchange);

            // 在then方法里的,相当于aop中的后置通知
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("  post 自定义过滤器工厂 AAAA " + this.getClass().getSimpleName());
            }));
        }

        @Override
        public int getOrder() {
            //数字越小,优先级越高
            return -100;
        }
    }

    //自定义的config类,用来设置传入的参数
    public static class Config{
        //Put the configuration properties for your filter here
        /**
         * 过滤类型
         */
        private String type;

        /**
         * 操作
         */
        private String type_2;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getType_2() {
            return type_2;
        }

        public void setType_2(String type_2) {
            this.type_2 = type_2;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "type='" + type + '\'' +
                    ", type_2='" + type_2 + '\'' +
                    '}';
        }
    }

}

application配置

server:
  port: 8090

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      # 路由 id
      routes:
        - id: study
          # 注册服务的名: lb://
          uri: lb://server-demo
          predicates:  #断言
            - Path=/index/**
#           - Query=paramA
           # - Before=2020-04-20T06:06:06+08:00[Asia/Shanghai]
          filters:
            - name: Test
              args:
                type: root
                type_2: 1112233333



          # 自定义 filters
      discovery:
        locator:
          enabled: true
      enabled: true
      httpclient:
        ssl:
          handshake-timeout: 10000
          close-notify-flush-timeout: 3000
          close-notify-read-timeout: 0
          use-insecure-trust-manager: true

# eureka
eureka:
  client:
    enabled: true
    service-url: # http://localhost:8761/eureka/
      defaultZone: http://localhost:8761/eureka/
    register-with-eureka: true
    fetch-registry: true

#
logging:
  level:
    #  root: debug
   org.springframework.cloud: debug

执行顺序


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容