摘要:将请求封装成将请求封装成的接口定义是但是最外层传进来的参数是和,需要将他们封装成,这个工作就是在中做的。其实主要任务就是将各种参数封装成除了和本次请求相关的和,还有会话管理器,编码解码器配置,国际化配置还有用于扩展。
接下来,将进入我们升级之路的又一大模块,即网关模块。网关模块我们废弃了已经进入维护状态的 zuul,选用了 Spring Cloud Gateway 作为内部网关。为何选择 Spring Cloud Gateway 而不是 nginx 还有 Kong 的原因是:
因此,我们使用了 Spring Cloud Gateway 作为内部网关,接下来,我们就来依次实现上面说的这些功能。同时在本次升级使用过程中, Spring Cloud Gateway 也有一些坑,例如:
但是首先,我们需要简单理解下 Spring Cloud Gateway 究竟包括哪些组件以及整个调用流程是什么样子的。由于 Spring Cloud Gateway 基于 Spring-Boot 和 Spring-Webflux 实现,所以我们会从外层 WebFilter 开始说明,然后分析如何走到 Spring Cloud Gateway 的封装逻辑,以及 Spring Cloud Gateway 包含的组件,请求是如何转发出去,回来后又经过了哪些处理,这些我们都会逐一分析。
为了详细分析流程,我们先来创建一个简单的网关,用于快速上手并分析。
首先创建依赖:
pom.xml
spring-cloud-parent com.github.jojotech 2020.0.3-SNAPSHOT 4.0.0 spring-cloud-api-gateway com.github.jojotech spring-cloud-webflux ${project.version} org.springframework.cloud spring-cloud-starter-gateway
parent 指向了我们项目的 spring-cloud-parent,同时加入了上一节实现的 spring-cloud-webflux 依赖,同时还需要加入 spring-cloud-starter-gateway,由于在我们的 spring-cloud-parent 已经指定了 spring-cloud-parent 的版本依赖管理,所以这里不需要指定 spring-cloud-starter-gateway 的版本
然后,我们开始编写配置文件:
application.yml
server: ##端口为 8181 port: 8181spring: application: # 微服务名称是 apiGateway name: apiGateway cloud: gateway: httpclient: # 网关转发到其他微服务的 HTTP 连接超时为 500ms connect-timeout: 500 # 网关转发到其他微服务的 HTTP 响应超时为 500ms response-timeout: 60000 routes: # 编写转发规则 - id: first_route # 转发到微服务 test-service uri: lb://test-service # 包含哪些路径 predicates: - Path=/test-ss/** # 转发到的微服务访问路径,去掉路径中的第一块,即去掉 /test-ss filters: - StripPrefix=1 loadbalancer: # 指定 zone,因为我们之前在负载均衡中加入了只有同一个 zone 的实例才能互相访问的逻辑 zone: test ribbon: # 关闭ribbon enabled: false cache: # 本地微服务实例列表缓存时间 ttl: 5 # 缓存大小,你的微服务调用多少个其他微服务,大小就设置为多少,默认256 capacity: 256 discovery: client: simple: # 使用 spring-common 中的简单 DiscoveryClient 服务发现客户端,就是将微服务实例写死在配置文件中 instances: # 指定微服务 test-service 的实例列表 test-service: - host: httpbin.org port: 80 metadata: # 指定该实例的 zone,因为我们之前在负载均衡中加入了只有同一个 zone 的实例才能互相访问的逻辑 zone: testeureka: client: # 关掉 eureka enabled: false
最后编写启动入口类:
package com.github.jojotech.spring.cloud.apigateway;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication(scanBasePackages = "com.github.jojotech.spring.cloud.apigateway")public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
启动,访问路径: http://127.0.0.1:8181/test-ss/anything
,可以看到请求被发送到 httpbin.org 的 anything 路径中,这个接口会返回请求中的所有信息。
这样,我们就实现了一个简单的网关。接下来我们来详细分析其工作流程和源码。
我们创建的简易网关,外层的服务容器其实就是基于 Netty 和 Project Reactor 的容器,我们跳过这些,直接进入 Spring Boot 相关的处理逻辑。我们只需要知道,请求和其对应的响应,会被外层的容器封装成为 ServerHttpRequest request
和 ServerHttpResponse response
(都在 org.springframework.http.server.reactive
这个包下)。
然后,会交由 WebHandler
进行处理。WebHandler
的实现,其实是一种责任链装饰模式,如下图所示。每一层的 WebHandler
会将 request
和 response
进行对应自己责任的装饰,然后交给内层的 WebHandler
处理。
WebHandler
的接口定义是:
public interface WebHandler { Mono handle(ServerWebExchange exchange);}
但是最外层传进来的参数是 request
和 response
,需要将他们封装成 ServerWebExchange
,这个工作就是在 HttpWebHandlerAdapter 中做的。HttpWebHandlerAdapter 其实主要任务就是将各种参数封装成 ServerWebExchange
(除了和本次请求相关的 request
和 response
,还有会话管理器 SessionManager,编码解码器配置,国际化配置还有 ApplicationContext 用于扩展)。
除了这些,处理 Forwarded
还有 X-Forwarded*
相关的 Header 的配置逻辑,也在这里进行。然后将封装好的 ServerWebExchange
交给内层的 WebHandler
即 ExceptionHandlingWebHandler
继续处理。同时,从源码中可以看出,交给内层处理的 Mono 还加入了异常处理和记录响应信息的逻辑:
//交给内层处理封装好的 `ServerWebExchange`return getDelegate().handle(exchange) //记录响应日志,trace 级别,一般用不上 .doOnSuccess(aVoid -> logResponse(exchange)) //处理内层没有处理的异常,一般不会走到这里 .onErrorResume(ex -> handleUnresolvedError(exchange, ex)) //在所有处理完成后,将 response 设为 complete .then(Mono.defer(response::setComplete));
剩下的内层的 WebHandler
,我们将在下一节中继续分析
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/125101.html
摘要:在这里,会将上下文中载入的拼接成,然后调用其方法的,它是的处理请求业务的起点。添加相关依赖之后,会有这个。路由权重相关配置功能相关实现类,这个我们这里不关心。本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们继续分析上一节提到的 WebHandler,经过将请求封装成 ServerWebExchange 的 HttpWebHand...
摘要:在这里,会将上下文中载入的拼接成,然后调用其方法的,它是的处理请求业务的起点。添加相关依赖之后,会有这个。路由权重相关配置功能相关实现类,这个我们这里不关心。 本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们继续分析上一节提到的 WebHandle...
摘要:添加相关依赖之后,会有这个。接着,根据的源码分析,会继续链路,到达下一个,即。在中,我们会计算出路由并发送请求到符合条件的。这个是的,会读取配置并生成路由。本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们继续分析上一节提到的 WebHandler。加入 Spring Cloud Sleuth 以及 Prometheus 相关依赖...
摘要:升级之路版基本流程讲解抽象类本系列代码地址我们继续分析上一节提到的。添加相关依赖之后,会有这个。路由权重相关配置功能相关实现类,这个我们这里不关心。这个是的,会读取配置并生成路由。 本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们继续分析上一节提到的 ...
摘要:对于异步的请求,使用的是异步客户端即。要实现的配置设计以及使用举例要实现的配置设计以及使用举例首先,我们要实现的,其包含三个重试重试的要在负载均衡之前,因为重试的时候,我们会从负载均衡器获取另一个实例进行重试,而不是在同一个实例上重试多次。 本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 为何需要封装异步 HT...
阅读 3664·2023-01-11 11:02
阅读 4206·2023-01-11 11:02
阅读 3004·2023-01-11 11:02
阅读 5145·2023-01-11 11:02
阅读 4699·2023-01-11 11:02
阅读 5483·2023-01-11 11:02
阅读 5234·2023-01-11 11:02
阅读 3858·2023-01-11 11:02