第2章 --- netty的源码分析

本文深入剖析Netty作为高性能网络应用框架的源码细节,包括ServerBootstrap的初始化过程,NioEventLoopGroup的工作原理,以及NioServerSocketChannel的创建与绑定流程。详细解读了事件循环、线程模型和I/O操作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新进入的公司是做股票mac,window app,公司选用netty作为行情推送数据,这一年多对netty源码可劲咬碎~~~~~~~~~~

先进行源码跟踪展示

-> AbstractBootstrap.bind(port)
 -> AbstractBootstrap.bind(address) 
 -> AbstractBootstrap.doBind(final SocketAddress localAddress) 
	-> AbstractBootstrap.initAndRegister----------------------------1
		-> io.netty.channel.ReflectiveChannelFactory.newChannel()---1.1实例化channel
		-> io.netty.bootstrap.AbstractBootstrap.init(Channel) ------1.2根据ServerBootStrap/BootStrap初始化channel
			-> EventLoopGroup.register------------------------------1.3.1 
			-> MultithreadEventLoopGroup.register(Channel)----------1.3.1 NioEventLoopGroup调用父类MultithreadEventLoopGroup.register
			-> SingleThreadEventLoop.register-----------------------1.3.2 next().register() 用执行器里面的真正对象NioEventLoop.register
			-> AbstractChannel.AbstractUnsafe.register--------------1.3.3 AbstractUnsafe#register初始化通道
			-> AbstractChannel.register0----------------------------1.3.4 注册,执行Event: HandlerAdded,传递Event: ChannelRegistered,判断是否传递Event: ChannelActive
			-> AbstractNioChannel.doRegister------------------------1.3.5 注册到java的Selector,未绑定事件,并且获得selectionKey,selector和channel绑定
 
	-> AbstractBootstrap.doBind0 
	-> io.netty.channel.AbstractChannel.bind(SocketAddress, ChannelPromise)--从tail(所有hand的头)开始绑定,pipeline.tail一直往上找到pipeline.head
	-> io.netty.channel.DefaultChannelPipeline.bind(SocketAddress, ChannelPromise)
	-> io.netty.channel.AbstractChannelHandlerContext.bind(SocketAddress, ChannelPromise)
	-> io.netty.channel.AbstractChannelHandlerContext.invokeBind(SocketAddress, ChannelPromise)
	-> io.netty.channel.DefaultChannelPipeline.HeadContext.bind(ChannelHandlerContext, SocketAddress, ChannelPromise)
	-> io.netty.channel.Channel.Unsafe.bind(SocketAddress, ChannelPromise)
	-> io.netty.channel.AbstractChannel.AbstractUnsafe.bind(SocketAddress, ChannelPromise)
	-> io.netty.channel.socket.nio.NioServerSocketChannel.doBind(SocketAddress)
		javaChannel().bind(localAddress, config.getBacklog());
		
		
	-> SingleThreadEventExecutor.execute ---------------------------NioEventLoop是的父类,执行
	-> SingleThreadEventExecutor.startThread()
	-> SingleThreadEventExecutor.doStartThread
	-> io.netty.channel.nio.NioEventLoop.run()
		-> #3 NioEventLoop.run() // for(;;)-loop
		-> #4 NioEventLoop.select(boolean oldWakenUp)
		-> #4 SingleThreadEventExecutor.runAllTasks(long timeoutNanos)
		-> io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(Set<SelectionKey>)
		-> io.netty.channel.nio.NioEventLoop.processSelectedKey(SelectionKey, AbstractNioChannel)---unsafe.read();
		-> io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe.read()
		-> io.netty.channel.socket.nio.NioServerSocketChannel.doReadMessages(List<Object>)
			-> SocketChannel ch = SocketUtils.accept(javaChannel());-我们熟悉的accept事件方法,等待新连接



	1、首先是new 一个ServerBootstrap,看ServerBootstrap的源码,其构造函数中没有什么初始化工作,并且,它是继承AbstractBootstrap类,其中大多数的工作都是其完成的。
	2、绑定了两个group,这两个group,一个是用来接收到连接请求时,处理,另一个是接收到数据时,处理的工作线程。
		1. 这里是使用的NioEventLoopGroup,它继承MultithreadEventLoopGroup,
		   在这个NioEventLoopGroup初始化时,会初始化线程池、Selector、ExecutorChooser(PowerOfTwoEventExecutorChooser)、队列拒绝handler、和EventLoop。这里初始化的是NioEventLoop。
		   并初始化一定数量(可以传递参数,或者是CPU线程数*2,或者是1)的NioEventLoop(相当于是线程)
		2. 而NioEventLoop继承了SingleThreadEventLoop,单线程处理提交的所有任务。主要是初始化任务队列LinkedBlockingQueue。并设置父EventLoop为NioEventLoopGroup。
		3. 以上,NIOEventLoopGroup初始化完成
	3、调用channel方法,并设置一个class。这个channel它是AbstractBootstrap的方法,主要功能是:
		1. 创建一个Channel的生成工厂,ReflectiveChannelFactory,而这个工厂的主要方法是newChannel,生成NioServerSocketChannel,它继承自AbstractNioMessageChannel类。这个channel后面再说。
	4、 调用childHandler方法,注册一个子的Handler,这个handler,主要是对worker线程使用。这里是new了一个ChannelInitializer类,它其实是继承了ChannelInboundHandlerAdapter。
		在它的抽象方法中,实现了在ChannelPipeline上注册Handler链。pipeline后面再说。
	5、第10至16设置TCP参数
	6、最后,调用bind方法。它也是在AbstractBootstrap中实现的。
		1. 在bind中,首先对地址和端口封装成SocketAddress,然后调用doBind方法。
		2. 在doBind中,首先调用的是initAndRegister方法,顾名思义,它就是初始化和注册Selector的。
		3. 在initAndRegister方法中,首先会初始化一个channel,也就是上面提到的ReflectiveChannelFactory的newChannel方法。生成NioServerSocketChannel。
			1. 在生成Channel时,使用的是反射的方式。这里着重看一下NioServerSocketChannel的初始化工作。
				1. 初始化时,先是创建了一个Java原生NIO的ServerSocketChannel,使用的是默认的SelectorProvider,也即调用的是SelectorProvider.provider()方法。
				2. 初始化AbstractNioMessageChannel,因为它继承了AbstractNioChannel类,所以还会初始化AbstractNioChannel类,而AbstractNioChannel继承了AbstractChannel。
					下面详细介绍这几个类中初始化的信息。
					1. 首先在AbstractChannel类中,生成了一个DefaultChannelId,
					2. 创建了Unsafe类,这个类使用的是newUnsafe方法,这个方法在AbstractNioMessageChannel中实现,生成其私有内部类NioMessageUnsafe,它只有read方法。
					3. 创建了上文提到的ChannelPipeline,这里创建的是DefaultChannelPipeline,并把自己传递到其中,这里也就是NioServerSocketChannel。
						在DefaultChannelPipeline中,主要是初始化了HeadContext和TailContext,
						其中HeadContext继承了AbstractChannelHandlerContext(也就是channelRead的ctx)、ChannelOutboundHandler、ChannelInboundHandler
						TailContext继承了AbstractChannelHandlerContext、ChannelInboundHandler
						1. HeadContext的功能:
							1. 初始化时,把它当成了outbound,因为它被设置成了true。
							2. 指定AbstractNioMessageChannel的unsafe类
							3. 其它的功能,在后续的代码分析中体现。
						2. TailContext的功能:
							1. 初始化时,把它当成了inbound,因为它被设置成了true。
					
					4. 设置了接受操作:OP_ACCEPT,设置channel为非阻塞模式。
					5. 创建了一个NioServerSocketChannelConfig对象,它继承了DefaultServerSocketChannelConfig类,传递进去Java NIO的ServerSocket。
						1. 会创建一个AdaptiveRecvByteBufAllocator分配策略类。
					以上,NioServerSocketChannel初始化完成。
			2. 调用ServerBootstrap的init方法
				这个方法的主要功能是设置TCP的参数,已经在Pipeline上注册一些handler。
				1. 获取到DefaultChannelPipeline,在这个Pipeline上注册ChannelInitializer,
				2. 异步执行在Pipeline上注册了一个ServerBootstrapAcceptor类,这个是ServerBootstrap的内部类,其功能是,用来接受连接的,主要是把由boss线程转移到worker线程
					并且设置了自动读取。
			以上初始化完成后,就开始了注册的流程。
			3. 调用NioEventLoopGroup的register方法
				1. 通过当前的值%size来获取一个NioEventLoop,最后会在AbstractUnsafe的register方法,并把NioEventLoop传过去。
				2. 调用AbstractNioChannel的doRegister方法,完成channel的注册。
				3. invokeHandlerAddedIfNeeded方法完成对handler的添加,因为,每次调用Pipeline的addLast方法时,都会创建一个AddTask,这时候,调用的就是这个TAsk。
					这时候主要是调用的是在ServerBootstrap中添加的ServerBootstrapAcceptor,也就是添加调用了ChannelInitializer的initChannel方法,最后把ChannelInitializer移除。
				4. 这时候调用fireChannelRegistered方法,主要是调用HeadContext、TailContext、ServerBootstrapAcceptor等的channelRegistered方法。
				5. isActive()判断,是否是活的,也就是是否已经绑定成功。这时候还没有做绑定操作,所以是false。
			以上完成了注册。
		4. 以上完成后,就进行了doBound操作。initAndRegister方法会返回一个ChannelFuture,判断其是否isDone,如果是true,则进行doBind0操作,这时候才是真正的bound。
			1. 这个都是异步操作。主要是调用channel的bound,也即NioServerSocketChannel,不过方法在AbstractChannel类中实现,最终调用DefaultChannelPipeline的bind。
			2. 在Pipeline中,主要是调用tail类的方法,然后找到是outbound的handler也即HeadContext进行bound,然后调用unsafe的bound。
			3. 这个unsafe是NioMessageUnsafe,不过方法是在AbstractUnsafe类中实现,最终还是调用NioServerSocketChannel的doBind方法。
			以上,就完成了bound操作。







 

如果能够解决您的问题,那是再好不过(✿◠‿◠) 。如果没有顺利的解决你的问题,那么请将您的问题留言给我~~~~~~~
再次感谢您能够浏览到这里,如有遗漏或错误,敬请斧正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值