Gateway 服务网关断言工厂

目录

 

什么是服务网关

服务网关的实现原理

断言工厂

AfterRoutePredicateFactory 断言工厂

BeforeRoutePredicateFactory 

BetweenRoutePredicateFactory

CookieRoutePredicateFactory

HeaderRoutePredicateFactory

HostRoutePredicateFactory

MethodRoutePredicateFactory

PathRoutePreidicateFactory

QueryRoutePredicateFactory

RemoteaddRoutePredicateFactory

 

自定义断言工厂

总结


什么是服务网关

服务网关是Spring Cloud 官方推出的第二代网关框架,用于替代第一代网关Netflix Zuul,其不仅提供了路由方式,并且基于Filter 链的方式提供了网关的基本功能;服务网关作为整个分布式服务的流量入口,有着举足轻重的作用,比如:

  • 协议转换,路由转发
  • 流量聚合,对流量进行监控,日志输出
  • 在网关层进行流量的控制
  • 在网关层做权限校验

服务网关的实现原理

Gateway 的核心组件是路由和过滤器,不同于Netflix Zuul 的是,Gateway 多了一个断言,用来判断请求交给哪一个Gateway web handler 进行处理。流程如下

首先请求交个Gateway handler mappering 处理,如果请求和断言匹配,则将请求交个Gateway web handler 处理。Gateway web handler 处理请求时会经过一系列Filter 链。如图所示,过滤器链被虚线一分为二,左边半部分是过滤器发送代理请求之前处理的,及pre 阶段,执行左边半部分一般可以实现限流、日志输出、鉴权等。右边半部分是请求之后处理的,及post 阶段,执行右边半部分可以实现对响应数据的修改,比如更改响应头和转换协议等;

断言工厂

当一个请求到来时,首先交个断言工厂进行处理,如果命中断言工厂,则执行下一步,否则返回错误信息;服务网关Gateway 内置了多个断言工厂,具体如下:

AfterRoutePredicateFactory 断言工厂

配置如下

spring:
    cloud:
        gateway:
            routes:
                -id: after_routes # 路由id,要保证id唯一。
                 uri: lb://alibaba-nacos # 请求转发路径
                 predicate:
                    -After= 2010-01-20T17:42:47.789-07:00[America/Denver] # 表示服务只能在配置日期后访问,并转发至http://alibaba-nacos/xxx
                

BeforeRoutePredicateFactory 

spring:
    cloud:
        gateway:
            routes:
                -id: before_routes # 路由id,要保证id唯一。
                 uri: lb://alibaba-nacos # 请求转发路径
                 predicate:
                    -Before= 2010-01-20T17:42:47.789-07:00[America/Denver] # 表示服务只能在配置日期前访问,并转发至http://alibaba-nacos/xxx
                

BetweenRoutePredicateFactory

spring:
    cloud:
        gateway:
            routes:
                -id: between_routes # 路由id,要保证id唯一。
                 uri: lb://alibaba-nacos # 请求转发路径
                 predicate:
                    -Between= 2017-01-20T17:42:47.789-07:00[America/Denver], 2027-01-21T17:42:47.789-07:00[America/Denver]  # 表示服务只能在配置日期时间段访问,并转发至http://alibaba-nacos/xxx
                

注意: 关于时间断言工厂,设置时有个讨巧的点就是通过ZonedDateTime.now() 打印时间包含时区

CookieRoutePredicateFactory

spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: lb://alibaba-nacos
          predicates:
            # 当且仅当带有名为somecookie,并且值符合正则ch.p的Cookie时,才会转发到用户微服务
            # 如Cookie满足条件,则访问http://localhost:8040/** -> user-center/**
            # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
            - Cookie=somecookie, ch.p

HeaderRoutePredicateFactory

spring:
  cloud:
    gateway:
      routes:
        - id: header_route
          uri: lb://alibaba-nacos
          predicates:
            # 当且仅当带有名为X-Request-Id,并且值符合正则\d+的Header时,才会转发到用户微服务
            # 如Header满足条件,则访问http://localhost:8040/** -> user-center/**
            # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
            - Header=X-Request-Id, \d+

HostRoutePredicateFactory

spring:
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: lb://alibaba-nacos
          predicates:
            # 当且仅当名为Host的Header符合**.somehost.org或**.anotherhost.org时,才会转发用户微服务
            # 如Host满足条件,则访问http://localhost:8040/** -> user-center/**
            # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
            - Host=**.somehost.org,**.anotherhost.org

MethodRoutePredicateFactory

		

spring:
  cloud:
    gateway:
      routes:
        - id: method_route
          uri: lb://alibaba-nacos
          predicates:
            # 当且仅当HTTP请求方法是GET时,才会转发用户微服务
            # 如请求方法满足条件,访问http://localhost:8040/** -> user-center/**
            # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
            - Method=GET

PathRoutePreidicateFactory

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: lb://alibaba-nacos
          predicates:
            # 当且仅当访问路径是/users/*或者/some-path/**,才会转发用户微服务
            # segment是一个特殊的占位符,单层路径匹配
            # eg. 访问http://localhost:8040/users/1 -> user-center/users/1
            - Path=/users/{segment},/some-path/**

QueryRoutePredicateFactory


spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: lb://user-center
          predicates:
            # 当且仅当请求带有名为foo的参数,且参数值符合正则ba.,才会转发到用户微服务
            # eg. 访问http://localhost:8040/users/1?baz=baz -> user-center的/users/1?baz=baz
            - Query=foo, ba.

RemoteaddRoutePredicateFactory

 

spring:
  cloud:
    gateway:
      routes:
        - id: remoteaddr_route
          uri: lb://user-center
          predicates:
            # 当且仅当请求IP是192.168.1.1/24网段,例如192.168.1.10,才会转发到用户微服务
            # eg. 访问http://localhost:8040/users/1 -> user-center的/users/1
            - RemoteAddr=192.168.1.1/24

自定义断言工厂

 如果说上边提供的系统断言工厂,不满足业务需求,那么我们可以实现自定义的断言工厂,通过观看源码得知,上述默认的断言工厂均继承于AbstractRoutePredicateFactory.那么我们要实现断言工厂首先需要继承AbstractRoutePredicateFactory ,并且需要注意的是: 自定义断言工厂类名后缀必须是xxxRoutePredicateFactory;

下面实现一个我们服务只能在每天指定时间段访问,具体实现如下:

package com.corn.gateway;

import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.List;
import java.util.function.Predicate;

/**
 * 自定义gateway 断言
 * @Author corn
 * @Date 2021/3/23 14:37
 */
@Slf4j
@Component
public class TimeBetweenRoutePredicateFactory extends AbstractRoutePredicateFactory<TimeBetweenRoutePredicateFactory.TimeBetweenConfig> {

    public TimeBetweenRoutePredicateFactory() {
        super(TimeBetweenConfig.class);
    }

    /**
     *@描述 gateway 断言具体执行逻辑
     *@参数
     *@返回值
     *@创建人  corn
     *@创建时间  2021/3/23
     */
    @Override
    public Predicate<ServerWebExchange> apply(TimeBetweenConfig config) {
        LocalTime start = config.getStart();
        LocalTime end = config.getEnd();
        return exchange->{
          return LocalTime.now().isAfter(start)&&LocalTime.now().isBefore(end);
        };
    }

    /**
     *@描述 用来将配置文件中的配置和TimeBetweenConfig 中的属性做映射
     *@参数
     *@返回值
     *@创建人  corn
     *@创建时间  2021/3/23
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Lists.newArrayList("start","end");
    }

  
    /**
     *@描述 设置参数
     *@参数 
     *@返回值 
     *@创建人  corn
     *@创建时间  2021/3/29
     */
    @Data
    protected  static class TimeBetweenConfig {
        private LocalTime start;
        private LocalTime end;
    }

    public static void main(String[] args) {
        // 获取gateway 支持的时间格式
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
        String format = dateTimeFormatter.format(LocalTime.now());
        System.out.println(format);
    }
}

 配置如下:

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: lb://alibaba-nacos
          predicates:
            - TimeBetween=上午5:00,下午11:59  # 这样就实现了我们的服务只能每天的早上5点到晚上的11:59 运行访问,其他时间段是不允许访问的

总结

本节讲述了服务网关gateway 的背景,组成部分,原理和断言工厂,断言其实决定了请求被路由Router 中,然后在断言处理之后,会进入过滤链Filter 逻辑中处理

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值