【001】webflux 源码解析 - 启动、执行流程

一、相关类结构

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下是否有对应的 DispatcherHandlerDispatcherServlet、以及ServletContainer Class字节码文件存在来决定当前是什么环境的

在这里插入图片描述

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

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

在这里插入图片描述

2、创建上下文

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

  • web servlet 环境 AnnotationConfigServletWebServerApplicationContext
  • web reactive 环境 AnnotationConfigReactiveWebServerApplicationContext
  • 默认非web环境 AnnotationConfigApplicationContext

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

3、刷新上下文 refresh

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

在这里插入图片描述

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

在这里插入图片描述

4、创建web服务器

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

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

  2. 通过 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.ServerManager
  • ServerManager.httpHandler = HttpWebHandlerAdapter
  • HttpWebHandlerAdapter 最终调用会委派给 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)) 结果处理

在这里插入图片描述

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值