Netty源码阅读系列-ServerBootstrap初始化流程

1,218 阅读3分钟

「我正在参与掘金会员专属活动-源码共读第一期,点击参与

本篇分析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中。

下面用一幅图说明下他们之间的关系。

image.png

ServerBootstrap的初始化流程

image.png

ServerBootStrap类用于方便的启动ServerChannel。

图中所示init方法的入参类型即是NioServerSocketChannel。

看看这个初始化方法主要都做了些什么:

  1. 设置一些配置和属性(setChannelOptions,setAttributes)

  2. 向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。

image.png

ServerBootstrapAcceptor又是什么, 让我们一探究竟。

ServerBootstrapAcceptor的职责

浏览ServerBootstrapAcceptor的代码, 可以看到比较关键的方法是ChannelRead方法。

image.png

该方法中的操作都是围绕着childChannel展开的, 主要做了以下事情:

  1. 设置childChannel的一些属性和配置。

  2. 将childHandler添加到childChannel的pipeline中。

  3. 向workGroup注册childChannel。

我们在方法上打断点, 并启用一个终端使用telnet连接到NettyServer, 观察该方法什么时候被触发。

image.png

image.png

注意这里的ServerBootstrapAcceptor的ChannelRead动作不是读数据, 传递过来的Object类型的msg也不是客户端发送的数据信息。该msg的真实类型是NioSocketChannel, 也就是与客户端关联的channel。

通过调用栈可以看到该方法被触发时是运行在bossGroup的线程中的。

image.png 当有新的连接建立时, 该方法被触发了。结合代码内容, 该类的职责就很清楚了:

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管理的线程中运行的。