`
budairenqin
  • 浏览: 199359 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Netty server端执行的各个阶段源码简单分析

阅读更多
简单过一下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)
分享到:
评论
2 楼 budairenqin 2013-07-08  
asialee 写道
不错,我也写了一个,不过没你的详细,呵呵:http://asialee.iteye.com/blog/1769508

相互学习
1 楼 asialee 2013-07-06  
不错,我也写了一个,不过没你的详细,呵呵:http://asialee.iteye.com/blog/1769508

相关推荐

Global site tag (gtag.js) - Google Analytics