Netty源码笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty源码笔记相关的知识,希望对你有一定的参考价值。

参考技术A Netty版本4.0.29.Final,以构造客户端连接服务端的角度来追踪源码

NioEventLoopGroup的构造器中会调用父类MultithreadEventLoopGroup的构造器

在父类MultithreadEventExecutorGroup的构造器中

上面已经完成了NioEventLoop的创建,并保存在NioEventLoopGroup的数组属性上。而关于NioEventLoop在具备线程池能力时,在何时启动已经创建的线程呢?在SingleThreadEventExecutor::execute中可以找到答案

而关于NioEventLoop内线程启动后的逻辑,可以在创建该线程时看到有向线程提交一个任务。根据任务内SingleThreadEventExecutor.this.run()可以定位到创建线程提交任务的NioEventLoop::run

NioEventLoop::run是Netty的核心所在。它是NioEventLoop的线程执行的唯一任务。方法内无限循环,阻塞等待IO事件或队列中的任务

关于队列中的任务从哪里来?一是源码内部,启动时会直接提交任务到队列中;二是可以直接取出channel中的NioEventLoop向其提交任务;三是使用Channel写数据时,都是以任务的形式提交到队列中。与Channel绑定的NioEventLoop循环时会消费提交到队列中任务并执行,后续在分析unsafe时会一并提及。

客户端Bootstrap配置引导时,需要指定Channel类型,后续会使用反射创建该Channel类型实例。

客户端完成NioEventLoopGroup和Bootstrap的创建及对Bootstrap进行相关的设置后,使用Bootstrap尝试与服务端建立连接。在同步与异步之间,推荐使用异步来监听连接事件的结果。

AbstractBootstrap是Bootstrap的父类,initAndRegister中完成了通道的创建、初始化以及注册

group()取到开始配置的NioEventLoopGroup,register在父类MultithreadEventLoopGroup中

虽说暂时不引入unsafe类逻辑,但在unsafe::register中,通道注册完成后会调用管道的fireChannelRegistered方法,进而执行自定义的ChannelInitializer,最终形成完整的管道。
目前管道上链表有三个节点:head、自定义ChannelInitializer、tail(规定自头向尾的流向为In,自尾向头的为Out)
它们的类型都是AbstractChannelHandlerContext,每个Context上都持有对应的ChannelHandler

至此,Channel的初始化及注册已经完成。回到Bootstrap::doConnect中,在Channel注册这个异步任务完成后,开始真正的连接服务端

channel连接建立完成后,可以使用channel写数据

写数据不会直接发送数据到服务端,而是会缓存起来,直到调用flush才会完成数据的最终发送。flush逻辑与写数据一样,channel到pipeline,tail到head。最终交由unsafe类来完成

以客户端建立连接发送数据流程为例(服务端大部分逻辑相似),总结Netty的工作流程:

以上是关于Netty源码笔记的主要内容,如果未能解决你的问题,请参考以下文章

Netty编解码开发+多协议开发和应用+源码+高级特性笔记免费送

Netty编解码开发+多协议开发和应用+源码+高级特性笔记免费送

美团大牛熬夜亲码 Netty 全栈笔记太强了!入门 / 中级 / 高级 / 源码 / 架构全都有!

美团大牛熬夜亲码 Netty 全栈笔记太强了!入门 / 中级 / 高级 / 源码 / 架构全都有!

85%java程序员不知道的Netty源码笔记,这就是他比我高10K的原因?

Netty核心技术及源码剖析-Netty入站与出站机制