深度解析Spring Cloud Gateway的底层实现原理

2024年 1月 29日 137.3k 0

作者 | 波哥

审校 | 重楼

Spring Cloud Gateway是一个基于Spring Framework 5和Project Reactor的响应式API网关,旨在为构建分布式微服务架构提供高性能和灵活的路由机制。底层实现基于Spring WebFlux框架,它使用WebFlux的HandlerMapping和HandlerAdapter来处理请求和生成响应;使用了反应式编程的思想,基于Project Reactor库实现异步、非阻塞的事件驱动架构,以提高性能和吞吐量。

本文将带你深入spring Cloud Gateway的底层实现原理,重点关注其核心组件和代码实现。

1. Spring Cloud Gateway核心组件

Spring Cloud Gateway的核心组件主要有:

  • Routes(路由):定义了URI、谓词(Predicates)和过滤器(Filters)的规则,用于将请求映射到后端服务。
  • Predicates(谓词):定义了匹配条件,用于决定请求是否应该映射到该路由。
  • Filters(过滤器):用于在请求和响应期间对请求和响应进行修改或转换。在调用过程中,会有多个过滤器形成过滤器链,用于处理请求、修改请求头、记录日志、限流等操作。

2.SpringCloud Gateway的具体使用

先来了解下Spring Cloud Gateway的具体使用过程,包括定义路由规则、自定义过滤器、启动应用等步骤。让我们逐步详细介绍这些步骤。

  • 定义路由规则

首先,在Spring Cloud Gateway中,我们需要定义路由规则。路由规则定义了请求该如何被路由到后端服务。这些规则通常以Java或YAML配置文件的形式提供,以YAML配置为例:

  • 自定义过滤器

我们可以编写自定义过滤器,对请求或响应进行特定的处理,例如添加头信息、修改请求、记录日志等。这里定义了要给GlobalFilter类型的过滤器,当然也可以定义非GlobalFilter类型的过滤器。

  • 启动应用

通过启动Spring Boot应用程序,Spring Cloud Gateway将开始监听配置的端口,并根据路由规则将请求转发到相应的后端服务。

  • 访问API

现在您可以通过访问定义的路由规则来测试API。

例如,对于上述路由规则的Java配置方式,可以使用以下URL访问API:

http://localhost:8080/sample/some-endpoint

Spring Cloud Gateway将根据路由规则将请求转发到http://example.com。

3.代码原理剖析

接下来,我们从上述使用案例入手,从GateWay的源码层面分析其底层实现原理。要理解其原理,其实只要理解如下这张图就足够了,所以接下来的分析我们将围绕这张图展开讲解。

Gateway作为网关,也就是统一的入口,它本身也是一个Web应用,在上面我们说过它是WebFlux框架,WebFlux大部分朋友可能都没接触过,我们可以使用SpringMVC进行类比。从上图我们可以看出,当请求到达Gateway后,首先会进入DispatcherHandler.handle方法进行处理,在该方法中调用GatewayHandlerMapping.getHandler方法,然后进入GatewayWebHandler.handle方法,随后进入Filter链进行处理,处理完成后调用具体的服务。综上,在整个的调用过程中使用到:DispatcherHandler、RoutePredicateHandlerMapping、SimpleHandlerAdapter、FilteringWebHandler几个核心的类(当然还使用到了Ribbon负载均衡、Netty/Nacos等注册中心相关的核心代码,不过本篇我们只分析Gateway相关源码),接下来我们将详细分析关键代码。

1.DispatcherHandler

该类做为Gateway的入口,接受所有网关的请求,类似于SpringMVC的DispatcherServlet类,所有的请求都将进入到handle方法中:

2.RoutePredicateHandlerMapping

这个RoutePredicateHandlerMapping就是上述handlerMappings的具体实现类,在handle方法就会使用到该类的实例,该类的主要作用是获取Route,也就是我们在配置文件中可能会配置多个Route,对于当前请求最终会使用哪个Route。

很多朋友会问:HandlerMappings有那么多实现类,你怎么知道会使用RoutePredicateHandlerMapping呢?

要回答这个问题,得对SpringBoot的底层实现有一定的了解,针对SpringBoot的底层实现大家可以看相关的文章,这里不做分析,在这里大家只需要寻找到

的spring.factories文件,SpringBoot会读取该文件中的配置,并将这些配置交由Spring容器管理就可以了。

在该配置中有一个配置类:GatewayAutoConfiguration,该配置类中完成对RoutePredicateHandlerMapping、FilteringWebHandler等的配置:

RoutePredicateHandlerMapping做为HandlerMapping的实现类,自然就会被调用到。

接下来我们看RoutePredicateHandlerMapping是如何帮我们寻找到Route的:

如上图代码所示,就是在lookupRoute方法中通过调用routeLocator.getRoutes方法获取到所有我们在应用配置文件中配置的Route(具体如何获取所有的Route源码比较简单,就是读取配置文件中的所有Route配置信息,这个大家可以自行去看下代码),然后调用getPredicate().apply方法确定具体的Route(也就是匹配断言),匹配成功后,会将该Route设置到exchange(可以理解为当前请求,即Request)的属性中:

exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR, r);

3.SimpleHandlerAdapter

上述获取到Route后,接下来会进入到DispatcherHandler.invokeHandler方法:

该方法会执行SimpleHandlerAdapter的handle方法:

该方法调用WebHandler.handle方法,也就是FilteringWebHandler。

4.FilteringWebHandler

进入FilteringWebHandler.handle方法后,会从exchange上下文中得到Route,一个Route中可能有多个GatewayFilter,这里将多个GatewayFilter生成一个DefaultGatewayFilterChain链对象,然后启动链调用,这过程中会完成一些列的动作,比如整合Ribbon负载均衡获取到服务实例(ServerInstantce),最终调用NettyRoutingFilter完成对服务的调用。如下是Spring Cloud Gateway框架内置的GlobalFilter:

全局过滤器

作用

Forward Routing Filter

用于本地forward,也就是将请求在Gateway服务内进行转发,而不是转发到下游服务

LoadBalancerClient Filter

整合Ribbon实现负载均衡,得到最终的ServerInstance

Netty Routing Filter

使用Netty的HttpClient转发http、https请求

Netty Write Response Filter

将代理响应写回网关的客户端侧

RouteToRequestUrl Filter

将从request里获取的原始url转换成Gateway进行请求转发时所使用的url

Websocket Routing Filter

使用Spring Web Socket将转发 Websocket 请求

Gateway Metrics Filter

整合监控相关,提供监控指标

本篇对Gateway的底层实现原理进行详细介绍,希望能对读者朋友们有所帮助。

作者介绍

波哥,互联行业从业10余年,先后担任项目总监及架构师。目前专攻技术,喜欢研究技术原理。技术全面,主攻Java,精通JVM底层机制及Spring全家桶底层框架原理,熟练掌握当前主流的中间件、服务网格等技术原理。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论