【001】webflux 源码解析

您所在的位置:网站首页 spring启动过程源码详解 【001】webflux 源码解析

【001】webflux 源码解析

2024-07-16 12:16| 来源: 网络整理| 查看: 265

文章目录 一、相关类结构1、启动设计到的类2、一次服务调用涉及到的类 二、webflux 启动流程1、首先 SpringApplication run 方法启动应用程序2、创建上下文3、刷新上下文 refresh4、创建web服务器5、启动服务器 三、webflux 一次服务调用流程1、HttpServerHandle2、ReactorHttpHandlerAdapter3、HttpWebHandlerAdapter4、DispatcherHandler

一、相关类结构 1、启动设计到的类 【spring-boot.jar、spring-web.jar】 // 入口 SpringApplication // 构造函数 SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class...) // run SpringApplication#run(java.lang.String...) // 创建上下文 SpringApplication#createApplicationContext() // 刷新上下文 SpringApplication#refreshContext(context) // 上下文 AnnotationConfigReactiveWebServerApplicationContext --> ReactiveWebServerApplicationContext // 刷新上下文 AbstractApplicationContext#refresh() // onRefresh方法 ReactiveWebServerApplicationContext#onRefresh() // 创建web服务器 ReactiveWebServerApplicationContext#createWebServer() // 刷新结束后,启动服务器 ReactiveWebServerApplicationContext#finishRefresh() // 上下文中,服务器管理器 ReactiveWebServerApplicationContext.ServerManager // 创建web服务器 ServerManager#ServerManager(ReactiveWebServerFactory factory, boolean lazyInit) // Netty服务工厂类 NettyReactiveWebServerFactory // 创建netty服务器,并绑定 ReactorHttpHandlerAdapter 业务适配器 NettyReactiveWebServerFactory#getWebServer(HttpHandler httpHandler) // 业务适配器 ReactorHttpHandlerAdapter // 最终刷新 ReactiveWebServerApplicationContext#finishRefresh() AbstractApplicationContext#finishRefresh() // 启动web服务器 ReactiveWebServerApplicationContext#startReactiveWebServer() // netty web服务器 NettyWebServer // 启动web服务器 NettyWebServer#start() // 开启异步守护线程专门给netty服务器 NettyWebServer#startDaemonAwaitThread 2、一次服务调用涉及到的类 【reactor-netty.jar、spring-web.jar】 // netty接收到请求之后 HttpServerHandle HttpServerHandle#onStateChange() // 调用适配器 ReactorHttpHandlerAdapter ReactorHttpHandlerAdapter#apply() ReactiveWebServerApplicationContext.ServerManager#handle() // 真正的处理器适配器 HttpWebHandlerAdapter HttpWebHandlerAdapter#handle() // 获取到委派类 DispatcherHandler WebHandlerDecorator#getDelegate() // 请求分发器 DispatcherHandler DispatcherHandler#handle() 二、webflux 启动流程

在这里插入图片描述

1、首先 SpringApplication run 方法启动应用程序

SpringApplication.run()

在这里插入图片描述

此时调用构造器,初始化属性 webApplicationType 获取web应用类型,这个地方判断应用类型根据classpath下是否有对应的 DispatcherHandler、DispatcherServlet、以及ServletContainer Class字节码文件存在来决定当前是什么环境的

在这里插入图片描述

调用run方法,是springboot项目启动流程的控制中心

createApplicationContext() 方法会根据上一步初始化 webApplicationType 类型,来决定创建哪种应用上下文refreshContext(context) 方法开始刷新应用上下文,刷新上下文其实是执行一些环境初始化动作

在这里插入图片描述

2、创建上下文

创建容器应用程序上下文时应根据环境类型的不同而创建不同的应用程序上下文。

web servlet 环境 AnnotationConfigServletWebServerApplicationContextweb reactive 环境 AnnotationConfigReactiveWebServerApplicationContext默认非web环境 AnnotationConfigApplicationContext

本节我们使用的是反应式Web环境,所以创建的应用程序上下文是AnnotationConfigReactiveWebServerApplicationContext的实例 在这里插入图片描述

3、刷新上下文 refresh

AbstractApplicationContext.refresh() 在 SpringApplication.run() 方法流程中,作为上下文刷新流程定义如下图。在AbstractApplicationContext.refresh() 中, 其中刷新流程中 onRefresh() 方法的真正实现交由子类完成 finishRefresh() 最终刷新步骤

在这里插入图片描述

上面刷新流程中,最终调用的是 ReactiveWebServerApplicationContext.onRefresh() 在这一步中,主要做的是创建web服务器,默认用的是netty

在这里插入图片描述

4、创建web服务器

ReactiveWebServerApplicationContext#createWebServer() 这边采用了简单工厂设计模式

首先获取一个 ReactiveWebServerFactory 工厂类,支持懒加载模式。那么 ReactiveWebServerFactory 的实现类的实例什么时候注入上下文容器中呢?其实这是借助了Springboot的 autoconfigure 机制,autoconfigure 机制会自动把 ReactiveWebServerFactory 的实现类NettyReactiveWebServerFactory 注入容器内

通过 ReactiveWebServerApplicationContext.ServerManager 内部服务器管理器类,管理web服务器,此处 get 去获取构造 ServerManager 实例

在这里插入图片描述

首先做了一个静默赋值,占坑,暂时并没有构造 handler 实例 factory.getWebServer(this) 这一步,通过上面我们说的工厂类去创建一个web服务器

在这里插入图片描述

构建netty服务器的同时,绑定 handlerAdapter,netty接收到请求之后,将请求交由 handlerAdapter处理

在这里插入图片描述

5、启动服务器

AbstractApplicationContext.refresh 刷新上下文中最后一个流程 finishRefresh() 处启动web服务器

在这里插入图片描述

ReactiveWebServerApplicationContext.ServerManager.start 由于调用start方法,传递的是方法引用 this::getHttpHandler ,也就是 ReactiveWebServerApplicationContext.getHttpHandler()

实际调试内容为 HttpWebHandlerAdapter [delegate=ExceptionHandlingWebHandler [delegate=FilteringWebHandler [delegate=org.springframework.web.reactive.DispatcherHandler@40d60f2]]] 最终请求会去委派给 DispatcherHandler

因为netty 服务器在接收到请求之后,需要交给对应的 httpHandler 进行具体的业务处理,所以,在启动之前需要初始化handler属性 HttpWebHandlerAdapter

在这里插入图片描述

继续看是怎么获取到 handler 的获取所有 HttpHandler 实现类,获取第一个返回

在这里插入图片描述

启动netty服务器 startDaemonAwaitThread(this.disposableServer); 主要用来 deamon线程同步等待服务终止这里之所以开启线程来异步等待服务终止,是因为这样不会阻塞调用线程,如果调用线程被阻塞了,则整个SpringBoot应用就运行不起来了

在这里插入图片描述

三、webflux 一次服务调用流程

当我们在浏览器敲入http://127.0.0.1:8080/getPerson时,会向WebFlux中的Netty服务器发起请求,服务器中的Boss监听线程会接收该请求,并在完成TCP三次握手后,把连接套接字通道注册到worker线程池的某个NioEventLoop中来处理,然后该NioEventLoop中对应的线程就会轮询该套接字上的读写事件并进行处理。

在这里插入图片描述

当注册到worker线程池的NioEventLoop上的连接套接字有读事件后,会调用processSelectedKeys方法进行处理,然后把读取的数据通过与该通道对应的管道DefaultChannelPipeline传播到注册的事件处理器进行处理。这里处理器HttpServerCodec负责把二进制流解析为HTTP请求报文,然后传递到管道后面的处理器HttpServerHandler中,HttpServerHandler会调用ServerContextHandler的createOperations方法,通过代码“channel.eventLoop().execute(op::onHandlerStart); ”把ChannelOperations的onHandlerStart方法作为任务提交到与当前通道对应的NioEventLoop管理的队列中。下面我们看NioEventLoop中的线程是如何执行该任务的

在这里插入图片描述

1、HttpServerHandle

netty 接收请求的部分就不看了,首先从netty的 reactor.netty.http.server.HttpServerHandle#onStateChange() 方法看起 此处会将请求转发给 ReactorHttpHandlerAdapter#apply()

在这里插入图片描述

在这里插入图片描述

2、ReactorHttpHandlerAdapter

调用适配器 ReactorHttpHandlerAdapter 的 apply 方法来具体处理请求 通过调试,我们也确定了 ReactorHttpHandlerAdapter 中的 httpHandler 实际上就是 ServerManager 对象,ServerManager中的 HttpHandler 最终会去调用真正的处理器 HttpWebHandlerAdapter [delegate=ExceptionHandlingWebHandler [delegate=FilteringWebHandler [delegate=org.springframework.web.reactive.DispatcherHandler@40d60f2]]]

从委派链来看,经过各个层最终请求将会给到 DispatcherHandler 这里采用了装饰器模式进行实现 梳理如下 :

ReactorHttpHandlerAdapter.httpHandler = ReactiveWebServerApplicationContext.ServerManagerServerManager.httpHandler = HttpWebHandlerAdapterHttpWebHandlerAdapter 最终调用会委派给 DispatcherHandler

在这里插入图片描述

继续看,此时会去调用 ServerManager#handle 方法

所以整个流程是 netty服务器 --> ReactorHttpHandlerAdapter.apply --> HttpWebHandlerAdapter.handle --> DispatcherHandler.handle

在这里插入图片描述

3、HttpWebHandlerAdapter 构造 ServerWebExchange 交换机getDelegate() 获取到分发器 DispatcherHandler

在这里插入图片描述

在这里插入图片描述

4、DispatcherHandler

DispatcherHandler#handle

fromIterable(this.handlerMappings) 获取所有的处理器映射concatMap(mapping -> mapping.getHandler(exchange)) 转换映射,获取处理器switchIfEmpty(createNotFoundError()) 不存在的时候抛出异常flatMap(handler -> invokeHandler(exchange, handler)) 发起调用flatMap(result -> handleResult(exchange, result)) 结果处理

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3