目录

【Spring Cloud】Gateway 服务网关核心架构的执行流程和断言

文章目录

基本概念

路由(Route)是gateway中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个信息:

  • id:路由标识符,区别于其他Route。
  • uri:路由指向的目的地uri,即客户端请求最终被转发到的微服务。
  • order:用于多个Route之间的排序,数值越小排序越靠前,匹配优先级越高。
  • predicate:断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
  • filter:过滤器用于修改请求和响应信息。

执行流程

执行流程大体如下:

  1. Gateway ClientGateway Server 发送请求;
  2. 请求首先会被 HttpWebHandlerAdapter 进行提取组装成网关上下文;
  3. 然后网关的上下文会传递到 DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
  4. RoutePredicateHandlerMapping 负责路由查找,并根据路由断言判断路由是否可用;
  5. 如果断言成功,由FilteringWebHandler创建过滤器链并调用;
  6. 请求会依次经过PreFilter->微服务->PostFiter的方法,最终返回响应;

断言

Predicate(断言,谓词)用于进行条件判断,只有断言都返回真,才会真正的执行路由。断言就是说: 在什么条件下才能进行路由转发。

内置路由断言工厂

Spring Cloud Gateway 包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体如下:

(1)基于Datetime类型的断言工厂,此类型的断言根据时间做判断,主要有三个:

  • AfterRoutePredicateFactory:接收一个日期参数,判断请求日期是否晚于指定日期;
  • BeforeRoutePredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期;
  • BetweenRoutePredicateFactory:接收两个日期参数,判断请求日期是否在指定时间段内;

- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]

(2)基于远程地址的断言工厂 RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中

- RemoteAddr=192.168.1.1/24

(3)基于Cookie的断言工厂 CookieRoutePredicateFactory ,接收两个参数:cookie名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。

- Cookie=chocolate, ch.

(4)基于Header的断言工厂 HeaderRoutePredicateFactory,接收两个参数:标题名称和正则表达式。判断请求Header是否具有给定名称且值与正则表达式匹配。

- Header=X-Request-ld, \d+

(5)基于Host的断言工厂 HostRoutePredicateFactory,接收一个参数:主机名模式。判断请求的Host是否满足匹配规则。

- Host=**.testhost.org

(6)基于Method请求方法的断言工厂 MethodRoutePredicateFactory,接收一个参数:判断请求类型是否跟指定的类型匹配。

- Method=GET

(7)基于Path请求路径的断言工厂 PathRoutePredicateFactory,接收一个参数:判断请求的URI部分是否满足路径规则。

- Path=/foo/{segment}

(8)基于Query请求参数的断言工厂 QueryRoutePredicateFactory,接收两个参数:请求param和正则表达式,判断请求参数是否具有给定名称且值与正则表达式匹配。

- Query=baz, ba.

(9)基于路由权重的断言工厂 WeightRoutePredicateFactory,接收一个[组名,权重],然后对于同一个组内的路由按照权重转发

yml 复制代码
- id: weight_route1
  uri: host1
  predicates:
	- Path=/product/**
	- Weight=group3, 1
- id: weight_route2
  uri: host2
  predicates:
	- Path=/product/**
	- Weight=group3, 9

接下来我们验证几个内置断言的使用:

yml 复制代码
server:
  port: 7000

spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true  # 让gateway可以发现nacos中的微服务
          lowerCaseServiceId: true # 将请求路径上的服务名配置为小写
      routes:
        - id: shop-product #当前路由标识,要求唯一
          uri: lb://shop-product #lb代表从nacos中获取微服务,shop-product是微服务的名称
          order: 1 #路由的优先级,数字越小级别越高
          predicates: #断言(就是路由转发要满足的条件)
            - Path=/product/** #当请求路径满足Path指定的规则时,才进行路由转发
            - Before=2019-08-30T15:46:00.000+08:00 #限制请求时间在2019-11-28之前
            - Method=POST #限制请求方式为post
          filters: #过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 #去掉请求路径的第一层

自定义路由断言工厂

我们来设定一个场景:假设我们的应用仅仅让age在(min,max)之间的人来访问。

1、在配置文件中,添加一个Age的断言配置

yml 复制代码
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true  # 让gateway可以发现nacos中的微服务
          lowerCaseServiceId: true # 将请求路径上的服务名配置为小写
      routes:
        - id: shop-product #当前路由标识,要求唯一
          uri: lb://shop-product #lb代表从nacos中获取微服务,shop-product是微服务的名称
          order: 1 #路由的优先级,数字越小级别越高
          predicates: #断言(就是路由转发要满足的条件)
            - Path=/product/** #当请求路径满足Path指定的规则时,才进行路由转发
            - Age=18,60 #限制年龄只有在18到60岁之间的人能访问
          filters: #过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 #去掉请求路径的第一层

2、自定义一个断言工厂,实现断言方法

java 复制代码
@Component
//泛型用于接收一个配置类,配置类用于接收配置文件中的配置。
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {

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

    /**
     * 用于从配置文件中获取参数值赋值到配置类中的属性上
     **/
    @Override
    public List<String> shortcutFieldOrder() {
        //这里的顺序要跟配置文件中的参数顺序一致
        return Arrays.asList("minAge","maxAge");
    }

    /**
     * 断言
     **/
    @Override
    public Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                //从 serverWebExchange 获取传入的参数
                String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("age");
                if(StringUtils.isNotEmpty(ageStr)) {
                    int age = Integer.parseInt(ageStr);
                    return age > config.getMinAge() && age < config.getMaxAge();
                }
                return true;
            }
        } ;
    }

    /**
     * 自定义一个配置类,用于接收配置文件中的参数
     **/
    @Data
    public static class Config {
        private int minAge;
        private int maxAge;
    }

}

3、启动测试

测试发现当age在(18,60)之间可以访问,其它范围不能访问。

总结

到这儿,Gateway 服务网关核心架构的执行流程和断言就已经介绍完了。下一篇将为大家带来Gateway 服务网关核心架构的过滤器相关的文章,敬请期待吧!

后续的文章,我们将继续完善我们的微服务系统,集成更多的Alibaba组件。想要了解更多JAVA后端知识,请点击文末名片与我交流吧。留下您的一键三连,让我们在这个寒冷的东西互相温暖吧!

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
funnycoding16 分钟前
mcp vs function call区别
前端·架构
Java技术小馆42 分钟前
如何处理消息堆积
java·面试·架构
DKPT1 小时前
系统设计模块之安全架构设计(常见攻击防御(SQL注入、XSS、CSRF、DDoS))
服务器·笔记·学习·架构·系统架构
学习2年半1 小时前
微服务相关
java·微服务·架构
soulermax2 小时前
华为数字芯片机考2025合集4已校正
华为·fpga开发·架构·github·硬件架构
笑远3 小时前
不同服务器架构(x86、ARM、Power、SPARC)对数据库使用的影响
运维·服务器·数据库·架构
season_zhu4 小时前
iOS开发:关于导航控制器
ios·架构·swift
西岭千秋雪_4 小时前
Sentinel核心算法解析の滑动窗口算法
分布式·算法·spring cloud·微服务·中间件·sentinel
数据智能老司机4 小时前
使用Python和PyTorch的生成式AI——开源大语言模型(LLMs)
pytorch·架构·llm
AronTing4 小时前
01-Spring Cloud Alibaba 微服务架构总览与核心组件详解
java·微服务·架构