前情提要
在Netty学习笔记之服务端启动一文中,我们了解了eventloop的基本功能,知道了它的一生其实就是个死循环,再循环里处理IO事件和taskQueue里面的任务;同时我们也了解到,在服务端启动之初(准确的来讲是在channel注册完成之后调用handlerAdded的时候)会给pipeline里添加一个特殊的handler:ServerBootstrapAcceptor,有了这两点之后,让我们看下Netty服务端启动后是如何利用reactor模型建立新连接的。
正文
当客户端启动并给服务端发送消息后,服务端的eventloop就会监听到对应事件:
NioEventLoop.run
1 | protected void run() { |
NioEventLoop.processSelectedKey
1 | private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { |
NioMessageUnsafe.read
1 | public void read() { |
最终调用了pipeline.fireChannelRead(readBuf.get(i)), 在服务端启动一文中我们也讲到了pipeline的传播,像这种firexxx的都是从head往后传播的,所以最终会传播到ServerBootstrapAcceptor里,调用ServerBootstrapAcceptor的channelRead,而这里,就是重头戏了。
ServerBootstrapAcceptor.channelRead
这里有几个点需要注意下:
代码①:这里的
Channel是SockerChannel,而不是ServerSocketChannel,即是客户端的Channel.代码②:
childHandler就是我们在boostrap里配的ChannelInitializer,等到channel真正注册后回调initChannel方法,把MyServerHandler添加到pipeline,见下图,这里的处理和服务端启动一文中doResigter一节中的代码②是一个道理,归根到底就是因为我们想给pipeline添加handler,但是Channel还没注册好,所以采取的一种妥协的方式,即先给pipeline注册一个ChannelInitializer类型的Handler,等到Channel真正注册好之后,再去回调这个特殊Handler的initChannel方法。这里也可以解释
bootstrap的handler和childHanlder的区别:前者对应ServerSocketChannel,后者对应SockerChannel.

代码③:这里就是将
channel注册到eventloop上,和我们在服务端启动一文中看到的serversocketChannel的注册差不多,但是有细微区别,主要体现在服务端启动时的注册是将
serversocketChannel注册到bossGroup里的eventloop.而childChannel注册时是要注册到workerGroup里。在注册环节,由于当前线程是
bossGroup的线程,所以一定会走else的逻辑, 将注册的任务提交到childChannel自己的eventloop