Spring Cloud Gateway解析

火山方舟向量数据库大模型

 Gateway( 网关),顾名思义,是出现在系统边界上的一个面向API或应用服务的、串行集中式的强管控服务,这里我们讨论的边界可以基于企业IT系统的边界,当然,可以理解为企业级应用防火墙,其目标主要起到隔离外部访问与内部系统交互的作用。在微服务概念的流行之前,网关就已经诞生了,在面向SOA体系中已经成熟,然而,随着微服务体系的快速发展,更进一步将Gateway推向更高的浪口。与其说网关催生了微服务体系,不如说微服务体系拥抱了网关。




   随着微服务架构概念的提出,API 网关成为了微服务架构的一个标配组件,无时无刻在我们的应用系统架构中起着举足轻重的作用,首先,我们来了解下基于Spring Cloud微服务体系网关的架构图,具体如下所示:

picture.image

    当我们谈论起网关,这玩意到底有什么用?具备哪些功能?具体我们可以参考以下模型图,具体:  

picture.image

    如上图所示:作为网关,其该具备的最基本的四大功能为:统一接入,流量管控,协议适配转发以及安全防护等。




    基于上述,我们分享了网关的历史以及其具备的基本功能,现在我们了解下在不同语言体系环境下所采用的网关技术,目前市面上或者业务场景落地解决方案中,常见的开源网关大致上按照语言分类有如下几类,具体如下图所示:

picture.image

   若按照使用范围、成熟度以及落地场景等来划分,目前主流网关技术应用涉及以下4 种:OpenResty、Kong、Zuul/Zuul 2、Spring Cloud Gateway,此外,随着Go语言在微服务领域的快速崛起以及应用,fagongzi API 网关最近也获得不少关注。因作者当前公司主要技术栈为Java,故本文重点以Spring Cloud Gateway网关为主,解析其基本原理以及在业务中的应用。




   

在Spring 的早期框架中,我们基本上用的是第一代Zuul,随着Spring 5的出现,Spring Cloud 开始完善其生态,引入多种不同的组件以支撑其在微服务体系领域中的地位。因此,Spring Cloud Gateway应运而生。

 Spring Cloud GatewaySpring Cloud 生态全新项目,其基于 Spring 5.0Spring Boot2.0Project Reactor 等技术开发的网关组件,旨在为微服务架构提供简单、有效和统一的 API 路由管理方式,同时提供安全性、监控/度量和限流,Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul。于是,大家肯定在想,这哥们疯了,Zuul2代了,还搞Gateway ?有意思吗?答案:当然。主要基于以下几点:
  • 提供更简单、高效的 API 网关。
  • Zuul 1.x 采用 Thread per connection 方式处理请求(每个请求一个线程进行处理),

一旦服务响应慢,线程会被阻塞不释放,存在性能瓶颈。

  • 虽然 Zuul 2.x 是适合高并发的版本,但是在 Zuul 2.x 开源前 Spring 团队启动了

Gateway。

    现在,我们来看下Spring Cloud Gateway的基本配置,具体如下所示,  





    pom.xml中的Maven依赖,具体可参考:  

          
<dependency>
          
    <groupId>org.springframework.cloud</groupId>
          
    <artifactId>spring-cloud-starter-gateway</artifactId>
          
</dependency>
      
    application.yml 配置,具体可参考:

          
spring:
          
  cloud:
          
    gateway:
          
      routes:
          
        - id: ${serviceId}
          
          uri: lb://${serviceName}    # http://localhost:8080/
          
          predicates:
          
            - Path= /api/**
          
          filters:
          
            - StripPrefix=1
      
  • id - 路由唯一 ID。
  • uri - 目标服务地址,支持普通 URL 和 lb://${服务名称}(表示从注册中心获取服务的

地址)。

  • predicates - 路由条件,匹配请求 URL 判断是否执行该路由。

  • filters - 过滤规则,包括 pre 和 post 过滤等相关规则。

      除此之外,我们还可以通过Java Bean来进行配置,具体如下所示:
    

          
@Configuration
          
public class GatewayConfig {
          

          
    @Bean
          
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
          
        return builder.routes()
          
                .route("path_route2", r -> r.path("/user/getByUsername")
          
                        .uri("http://localhost:8201/user/getByUsername"))
          
                .build();
          
    }
          
}
      
    现在,我们继续了解Spring Cloud Gateway 的基本原理,我们先看下其架构图,具体如下所示:

picture.image

   基于上述拓扑,我们可以看到:S

pring Cloud Gateway 依 赖 Spring Boot 和 Spring Webflux 提供的 Netty runtime,启动时 Netty Server 监听指定端口,接受客户端请求。 请求处理过程如下图,几个重要组成部分:

   1、路由(Route),网关的基本组件,由 ID、目标 URI、Predicate 集合和 Filter 集合组成。




  2、Predicate,Java 8 引入的函数式接口,提供断言(assert)功能,可以匹配 HTTP 请求中的任何内容,如果 Predicate 集合判断结果是 true,表示请求会由该 Route 进行转发。




  3

Filter,为请求提供前置(pre)和后置(post)过滤。

   现在,我们来了解下其工作流原理,基本的处理流程及架构图如下:  

picture.image

   基于上述处理图,我们可以得知:






   1、Gateway接受客户端请求;




   2、网关处理程序映射确定请求与路由匹配,匹配成功则将其发送到网关Web处理程序;




   3、Web处理程序处理程序通过特定于请求的过滤器链运行请求:

请求经过 Filter 过滤器链,执行 pre 处理逻辑,如修改请求头信息等; 发出代理请求,请求被转发至下游服务并返回响应。

   4、响应经过 Filter 过滤器链,执行 post 处理逻辑。




   5、向客户端响应应答。




   再此,我们看下Spring Cloud Gateway源码实现,以便能够更清晰地去熟悉其内部具体实现细节,具体如下所示:




    网关初始化,启动注解:@GatewayAutoConfiguration(spring-cloud-gateway

-core#org.springframework.cloud.gateway.config),源码如下:


          
@Service
          
public class XXXGatewayFilterFactory extends AbstractGatewayFilterFactory<XXXConfig> {
          
  
          
    @Override
          
    public GatewayFilter apply(final XXXConfig config) {
          
        return (((exchange, chain) -> {
          
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
          
                // ...
          
            }));
          
        }));
          
    }
          

          
    @Data
          
    public static class XXXConfig {
          

          
        private String name;
          
    }
          
}
      
   Spring Cloud Gateway 基于 Spring WebFlux 实现,@GatewayClassPathWarningAutoConfiguration 注解用于用于检查项目是否正确导入 spring-boot-starter-webflux 依赖,而不是错误导入 spring-boot-starter-web 依赖。




  @GatewayLoadBalancerClientAutoConfiguration 初始化 LoadBalancerClientFilter 实现负载均衡。




   @GatewayAutoConfiguration 中实现多个核心 Bean 的初始化。

Gateway 的配置参数参考 GatewayProperties.class。其基本组件简要源码实现如下:

   Route,作为

Gateway 中最基本的组件之一,表示一个具体的路由信息载体。源码如下所示:


          
public class Route implements Ordered {
          
    private final String id;
          
    private final URI uri;        // 路由指向的目的地 uri
          
    private final int order;      // 多个 Route 之间的排序,数值越小排序越靠前
          
    private final AsyncPredicate<ServerWebExchange> predicate;    // 匹配 Route 的条件
          
    private final List<GatewayFilter> gatewayFilters;              // 应用于 Route 的过滤器
          
}
      
   Predicate 组件用于匹配请求和 Route,其总共定义3 种逻辑操作方法:and/or/negate。源码如下所示:

          
public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> {
          
    default AsyncPredicate<T> and(AsyncPredicate<? super T> other) {
          
        // 两个 Predicate 同时满足
          
    }
          

          
    default AsyncPredicate<T> negate() {
          
        // 对 Predicate 匹配结果取反
          
    }
          

          
    default AsyncPredicate<T> or(AsyncPredicate<? super T> other) {
          
        // 两个 Predicate 只需满足其一
          
    }
          
}
      
   Filter 组件功能主要用于请求代理之前或之后,最终通过 filter chain 形成链式进行调用,每个filter处理完pre filter逻辑后委派给 filter chain,其再委派给下一个filter。具体源码如下:

          
public interface GatewayFilter extends ShortcutConfigurable {
          

          
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
          
}
          

          
public interface GatewayFilterChain {
          
    Mono<Void> filter(ServerWebExchange exchange);
          
}
      
   接下来,我们再看下

RouteLocator,其主要 用于获取 Route,通过 RouteDefinitionLocator 获取到 RouteDefinition,然后转换成Route,源码如下所示:


          
public interface RouteLocator {
          
    Flux<Route> getRoutes();
          
}
          

          
public class RouteDefinitionRouteLocator implements RouteLocator, 
          
        BeanFactoryAware, ApplicationEventPublisherAware {
          
  
          
    private final RouteDefinitionLocator routeDefinitionLocator;
          
    // RoutePredicateFactory 列表
          
    private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap();
          
    // GatewayFilterFactory 列表
          
    private final Map<String, GatewayFilterFactory> gatewayFilterFactories = new HashMap();
          
                                                      
          
    public Flux<Route> getRoutes() {
          
        return this.routeDefinitionLocator.getRouteDefinitions()
          
                .map(this::convertToRoute)
          
                .map((route) -> {
          
                    if (this.logger.isDebugEnabled()) {
          
                        this.logger.debug("RouteDefinition matched: " + route.getId());
          
                    }
          

          
                    return route;
          
                });
          
    }
          
                                                      
          
    private Route convertToRoute(RouteDefinition routeDefinition) {
          
        AsyncPredicate<ServerWebExchange> predicate = this.combinePredicates(routeDefinition);
          
        List<GatewayFilter> gatewayFilters = this.getFilters(routeDefinition);
          
        return ((AsyncBuilder)Route
          
                    .async(routeDefinition)
          
                    .asyncPredicate(predicate)
          
                    .replaceFilters(gatewayFilters))
          
                .build();
          
    }
          
}
      

路由匹配部分,Spri ng WebFlux 的访问入口 org.springframework.web.reactive.DispatcherHandler(对应 MVC 中的 DispatcherServlet),具体源码可参考如下:


          
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
          
    private List<HandlerMapping> handlerMappings;
          
    private List<HandlerAdapter> handlerAdapters;
          

          
    public Mono<Void> handle(ServerWebExchange exchange) {
          
        // 顺序使用 handlerMappings 获得对应的 WebHandler,invoke 执行
          
        return Flux.fromIterable(this.handlerMappings)
          
            // RoutePredicateHandlerMapping
          
            .concatMap((mapping) -> { return mapping.getHandler(exchange); })
          
            .next()
          
            .switchIfEmpty(this.createNotFoundError())
          
            // SimpleHandlerAdapter
          
            .flatMap((handler) -> { return this.invokeHandler(exchange, handler); })
          
            .flatMap((result) -> { return this.handleResult(exchange, result); });
          
    }
          
}
      
   RoutePredicateHandlerMapping 匹配路由,源码如下:

          
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
          
    private final FilteringWebHandler webHandler;
          
    private final RouteLocator routeLocator;
          
   
          
    // mapping.getHandler(exchange); 会调用至此
          
    protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
          
        return this.lookupRoute(exchange)    // 匹配 Route
          
            .flatMap((r) -> {
          
                // ...
          
                return Mono.just(this.webHandler);
          
            })
          
            .switchIfEmpty(/**未匹配到 Route**/);
          
    }
          
}
      
   最后,我们在了解下

Filter chain,SimpleHandlerAdapter 循环执行 WebHandler,我们以 FilteringWebHandler 为例,创建 GatewayFilterChain 处理请求,具体源码如下:


          
public class SimpleHandlerAdapter implements HandlerAdapter {
          
    public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
          
        WebHandler webHandler = (WebHandler)handler;
          
        Mono<Void> mono = webHandler.handle(exchange);
          
        return mono.then(Mono.empty());
          
    }
          
}
          

          
public class FilteringWebHandler implements WebHandler {
          
    public Mono<Void> handle(ServerWebExchange exchange) {
          
        Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
          
        List<GatewayFilter> gatewayFilters = route.getFilters();
          
        List<GatewayFilter> combined = new ArrayList(this.globalFilters);
          
        // 合并 GlobalFilter 和 GatewayFilter,整体排序
          
        combined.addAll(gatewayFilters);
          
        AnnotationAwareOrderComparator.sort(combined);
          
      
          
        // 创建 GatewayFilterChain 处理请求
          
        return (new FilteringWebHandler.DefaultGatewayFilterChain(combined))
          
          .filter(exchange);
          
    }
          
}
      
   至此,Spring Cloud Gateway基本解析到此为止,

大家有什么问题或者建议,欢迎随时留言沟通。

  • EOF -

点击关注公众号:" 牧师架构之路 "

如果您喜欢本文,欢迎点击右上角,把文章分享到朋友圈~~~

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
火山引擎AB测试总体经济影响
为充分了解火山引擎A/B测试平台为企业带来的潜在投资回报,火山引擎委托Forrester Consulting使用总 体经济影响(TEI)模型进行对其A/B测试产品潜在的投资回报率(ROI)进行评估分析。该研究的目的是为了给读者提供火山引擎A/B测试产品带来潜在财务影响评估的参考。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论