简单过一下Netty3.6.6.Final源码,让自己对各个流程有个稍微清晰的理解,只是文字描述,尽量描述简单,有时间再画画图
Server启动:
1.new ServerBootstrap
构造NioServerSocketChannelFactory,用来创建NioServerSocketChannel对象(newChannel方法)
1..NioServerSocketChannel:是一个parent Channel,负责接收客户端进来的连接并创建child Channel
2..NioServerSocketChannelFactory中有两类线程池:
1...BossPool<NioServerBoss> bossPool
boss线程池:每个绑定的ServerSocketChannel都有自己的boss线程池,默认为一个线程,它负责接收客户端进来的连接,一旦连接成功,boss线程将Channel交给其中一个worker线程来处理
2...WorkerPool<NioWorker> workerPool
work线程池:对多个Channel执行非阻塞的读写,Netty中默认为cpu核心数*2条worker线程,如果不使用worker来执行业务操作,我喜欢将worker线程数量定在cpu核心数+1,这样比较适合执行cpu密集型任务
3..NioServerSocketChannelFactory还有一个重要对象:
NioServerSocketPipelineSink sink
接收并处理下行(downstream)末端(注意下行的末端是pipeline的头结点)的ChannelEvent
2.ServerBootstrap#bind
创建一个绑定了local address的parent Channel,阻塞到绑定成功为止
1..newChannel(创建NioServerSocketChannel),传入bossPipeline、NioServerSocketChannelFactory中的sink、bossPool(如果有多个只传入一个)、workerPool
1...ServerSocketChannel.open()一个ServerSocketChannel并设置为非阻塞模式
2...bossPipeline:默认有一个Binder,主要做以下事情:
1....处理parent Channel open,负责setOptions,以及fire ChannelState.BOUND事件
2....处理child Channel open,负责setOptions
3....对bind过程中的异常进行处理
2..在NioServerSocketChannel中fireChannelOpen,由上面的Binder处理这个parent Channel open事件
parent Channel open流程:
1...设置child pipelineFactory
2...setOptions
3...fire ChannelState.BOUND downstream事件
sink#eventSunk
handleServerSocket
NioServerBoss#bind
构造NioServerBoss$RegisterTask并加入taskQueue队列
3..boss线程中(NioServerBoss.RegisterTask类中)将parent Channel向selector中注册SelectionKey.OP_ACCEPT
4..bind成功返回parent Channel
================================================================================
Accepts incoming connection
1.boss[NioServerBoss]#process中调用selector.selectedKeys()拿到OP_ACCEPT的就绪parent Channel
2.boss[NioServerBoss]#process中调用parentChannel.socket.accept()创建child Channel (acceptedSocket)
3.boss[NioServerBoss]#process#registerAcceptedChannel,接收连接
1..拿到一个worker线程
2..将child Channel、parent Channel、child pipeline、sink、worker线程、boss线程组合起来构造一个NioAcceptedSocketChannel
1...设置此Channel为连接状态
2...在parent Channel的pipeline中fire child Channel state changed(child ChannelState有OPEN和CLOSED两个状态,这里是fire child ChannelState.OPEN)
1....构造ChildChannelStateEvent
2....Binder中处理child Channel open(如上文描述,就是setOptions,比如sendBufferSize、tcpNoDelay等属性)
3...在自己的child pipeline(就是我们自己定义的pipeline了)中fire child ChannelState.OPEN
3..将构造好的NioAcceptedSocketChannel向worker中注册(也就是加入到此worker的任务队列taskQueue中)
4.切换到worker线程,向worker的Selector中注册之前boss接收并创建好的child Channel(Selectionkey.OP_READ)
================================================================================
Read
1.worker调用selector.selectedKeys()拿到OP_READ的就绪child Channel
2.NioWorker.read(SelectionKey k)
1.. 分配buffer
2.. fire MessageReceived事件
3.在child pipeline调用链中执行MessageReceived
================================================================================
Write
1.构造DownstreamMessageEvent并send downstream事件,child pipeline调用链中执行(注意downstream从pipeline队尾开始)
2.在sink中将上面的DownstreamMessageEvent offer到此Channel的writeBufferQueue
3.AbstractNioWorker#write0()
1..writeBufferQueue.poll()出上面的DownstreamMessageEvent
2..分配writeBuffer
3..buf.transferTo对应child Channel
4..fire WriteComplete事件(upstream,从pipeline头结点开始)
在child pipeline调用链中执行WriteCompletion事件(如果你使用了链路空闲检测handler,比如IdleStateHandler,会在writeComplete方法中更新lastWriteTime)
Server启动:
1.new ServerBootstrap
构造NioServerSocketChannelFactory,用来创建NioServerSocketChannel对象(newChannel方法)
1..NioServerSocketChannel:是一个parent Channel,负责接收客户端进来的连接并创建child Channel
2..NioServerSocketChannelFactory中有两类线程池:
1...BossPool<NioServerBoss> bossPool
boss线程池:每个绑定的ServerSocketChannel都有自己的boss线程池,默认为一个线程,它负责接收客户端进来的连接,一旦连接成功,boss线程将Channel交给其中一个worker线程来处理
2...WorkerPool<NioWorker> workerPool
work线程池:对多个Channel执行非阻塞的读写,Netty中默认为cpu核心数*2条worker线程,如果不使用worker来执行业务操作,我喜欢将worker线程数量定在cpu核心数+1,这样比较适合执行cpu密集型任务
3..NioServerSocketChannelFactory还有一个重要对象:
NioServerSocketPipelineSink sink
接收并处理下行(downstream)末端(注意下行的末端是pipeline的头结点)的ChannelEvent
2.ServerBootstrap#bind
创建一个绑定了local address的parent Channel,阻塞到绑定成功为止
1..newChannel(创建NioServerSocketChannel),传入bossPipeline、NioServerSocketChannelFactory中的sink、bossPool(如果有多个只传入一个)、workerPool
1...ServerSocketChannel.open()一个ServerSocketChannel并设置为非阻塞模式
2...bossPipeline:默认有一个Binder,主要做以下事情:
1....处理parent Channel open,负责setOptions,以及fire ChannelState.BOUND事件
2....处理child Channel open,负责setOptions
3....对bind过程中的异常进行处理
2..在NioServerSocketChannel中fireChannelOpen,由上面的Binder处理这个parent Channel open事件
parent Channel open流程:
1...设置child pipelineFactory
2...setOptions
3...fire ChannelState.BOUND downstream事件
sink#eventSunk
handleServerSocket
NioServerBoss#bind
构造NioServerBoss$RegisterTask并加入taskQueue队列
3..boss线程中(NioServerBoss.RegisterTask类中)将parent Channel向selector中注册SelectionKey.OP_ACCEPT
4..bind成功返回parent Channel
================================================================================
Accepts incoming connection
1.boss[NioServerBoss]#process中调用selector.selectedKeys()拿到OP_ACCEPT的就绪parent Channel
2.boss[NioServerBoss]#process中调用parentChannel.socket.accept()创建child Channel (acceptedSocket)
3.boss[NioServerBoss]#process#registerAcceptedChannel,接收连接
1..拿到一个worker线程
2..将child Channel、parent Channel、child pipeline、sink、worker线程、boss线程组合起来构造一个NioAcceptedSocketChannel
1...设置此Channel为连接状态
2...在parent Channel的pipeline中fire child Channel state changed(child ChannelState有OPEN和CLOSED两个状态,这里是fire child ChannelState.OPEN)
1....构造ChildChannelStateEvent
2....Binder中处理child Channel open(如上文描述,就是setOptions,比如sendBufferSize、tcpNoDelay等属性)
3...在自己的child pipeline(就是我们自己定义的pipeline了)中fire child ChannelState.OPEN
3..将构造好的NioAcceptedSocketChannel向worker中注册(也就是加入到此worker的任务队列taskQueue中)
4.切换到worker线程,向worker的Selector中注册之前boss接收并创建好的child Channel(Selectionkey.OP_READ)
================================================================================
Read
1.worker调用selector.selectedKeys()拿到OP_READ的就绪child Channel
2.NioWorker.read(SelectionKey k)
1.. 分配buffer
2.. fire MessageReceived事件
3.在child pipeline调用链中执行MessageReceived
================================================================================
Write
1.构造DownstreamMessageEvent并send downstream事件,child pipeline调用链中执行(注意downstream从pipeline队尾开始)
2.在sink中将上面的DownstreamMessageEvent offer到此Channel的writeBufferQueue
3.AbstractNioWorker#write0()
1..writeBufferQueue.poll()出上面的DownstreamMessageEvent
2..分配writeBuffer
3..buf.transferTo对应child Channel
4..fire WriteComplete事件(upstream,从pipeline头结点开始)
在child pipeline调用链中执行WriteCompletion事件(如果你使用了链路空闲检测handler,比如IdleStateHandler,会在writeComplete方法中更新lastWriteTime)