「我正在参与掘金会员专属活动-源码共读第一期,点击参与」
本篇分析ServerBootstrap的init方法, 并着重关注ServerBootstrapAcceptor类的职责。探索Netty服务端启动流程。
一些前置知识
在探索Netty启动流程之前, 还是要了解一些前置知识的, 可以让我们在后续的源码阅读中更轻松更连贯。
NioServerSocketChannel与 NioSocketChannel
在Java传统BIO中大家应该见过ServerSocket和Socket, ServerSocket负责监听一个端口accept连接,accept函数调用后会返回一个与双端关联的普通Socket,后续与客户端的IO交互都是通过这个普通Socket。
理解了ServerSocket与Socket的区别,再去理解Netty中的NioServerSocketChannel与NioSocketChannel的区别与职责就很容易了,NioServerSocketChannel负责accept新的连接,NioSocketChannel负责后续的IO交互。
bossGroup与workGroup
Netty的线程模型还是要先简单了解一下。
在Netty中tcp连接的accept操作和读写操作是不需要我们自己维护线程的。Netty启动时要指定bossGroup和workGroup,他们被用于处理ServerChannel和ClientChannel的事件和后续IO操作。
NioServerSocketChannel被注册到bossGroup中。
NioSocketChannel被注册到workGroup中。
下面用一幅图说明下他们之间的关系。
ServerBootstrap的初始化流程
ServerBootStrap类用于方便的启动ServerChannel。
图中所示init方法的入参类型即是NioServerSocketChannel。
看看这个初始化方法主要都做了些什么:
-
设置一些配置和属性(setChannelOptions,setAttributes)
-
向NioServerSocketChannel的pipeline添加一个Handler
这个Handler的类型是ChannelInitializer, 看一下它的注释:
A special ChannelInboundHandler which offers an easy way to initialize a Channel once it was registered to its EventLoop.
这是一个特别的InboundHandler, 它提供了一个initChannel的回调函数, 当channel被注册到EventLoop后, 该回调会被触发, 使调用方可以在此时装配该channel的pipeline。
现在回到代码流程中来, NioServerSocketChannel在被注册到bossGroup之后就会触发initChannel方法, 在回调中装配该socketChannel的pipeline。
从代码中看可以到initChannel又向pipeline中添加了一个Handler, 不过这次该Handler的类型是ServerBootstrapAcceptor。
ServerBootstrapAcceptor又是什么, 让我们一探究竟。
ServerBootstrapAcceptor的职责
浏览ServerBootstrapAcceptor的代码, 可以看到比较关键的方法是ChannelRead方法。
该方法中的操作都是围绕着childChannel展开的, 主要做了以下事情:
-
设置childChannel的一些属性和配置。
-
将childHandler添加到childChannel的pipeline中。
-
向workGroup注册childChannel。
我们在方法上打断点, 并启用一个终端使用telnet连接到NettyServer, 观察该方法什么时候被触发。
注意这里的ServerBootstrapAcceptor的ChannelRead动作不是读数据, 传递过来的Object类型的msg也不是客户端发送的数据信息。该msg的真实类型是NioSocketChannel, 也就是与客户端关联的channel。
通过调用栈可以看到该方法被触发时是运行在bossGroup的线程中的。
当有新的连接建立时, 该方法被触发了。结合代码内容, 该类的职责就很清楚了:
ServerBootstrapAcceptor的职责是accept新的连接后对新建立的childChannel(NioSocketChannel)进行配置。包括向childChannel的pipeline中添加后续IO处理的Handler。并且在配置完成后将childChannel注册到workGroup中去。
本篇总结
Netty的启动流程中ServerBootstrap类中的init方法比较关键, 该方法的入参包含一个NioServerSocket类型的serverChannel, 它将一个初始化Handler添加到serverChannel的pipeline中, 并将serverChannel注册到bossGroup中。
以上动作是在main线程中运行的。
当serverChannel被成功注册到bossGroup后会触发初始化Handler的initChannel回调, 在该回调中又向serverChannel的pipieline中添加了一个Handler, 该handler就是ServerBootstrapAcceptor。
当新的连接建立后, ServerBootstrapAcceptor的channelRead方法被触发, 带着一个NioServerSocket类型的childChannel, ServerBootstrapAcceptor负责配置该childChannel, 将需要的Handler添加到childChannel的pipieline中, 并将childChannel注册到workGroup中。
以上动作是在bossGroup管理的线程中运行的。