Netty源码分析 ServerBootstrap服务端启动
本文使用
netty-4.1.5.Final
版本源码进行分析
ServerBootstrap是Socket服务端的启动辅助类,用户通过ServerBootstrap可以方便的创建Netty的服务端,并加以定制。下面我们看一下服务端ServerBootstrap如何启动并对启动过程的源码进行分析。
ServerBootstrap服务端启动
|
|
创建ServerBootstrap实例,绑定用于监听TCP连接的bossGroup和用于处理I/O事件及task任务的workerGroup,并设置其他相关定制参数,最后绑定一个监听TCP连接的端口,就完成了启动Netty服务端的代码。
ServerBootstrap服务端启动源码分析
创建ServerBootstrap实例
|
|
设置ServerBootstrap参数
绑定Reactor线程池
|
|
parentGroup线程组主要用于处理TCP连接请求,childGroup线程组主要用于I/O读写以及task执行。
设置channel类型,用于根据class类型反射创建对应channel
|
|
根据channel的类型,创建一个生产channel的工厂,用于通过channel类型反射创建对应的channel,服务端一般使用NioServerSocketChannel.class
。
设置channel参数
|
|
设置handler
|
|
为NioServerSocketChannel设置ChannelHandler。
设置子handler
|
|
每个NioSocketChannel设置ChannelHandler,ChannelHandler是netty提供给用户定制和扩展的关键接口,用户可以通过自定义ChannelHandler,添加具体的业务逻辑处理。
启动ServerBootstrap的核心逻辑源码分析
绑定一个监听端口来启动服务端ServerBootstrap,绑定操作不仅要绑定端口并设置监听,首先需要将Channel初始化并注册到eventLoop中。
ServerBootstrap启动的核心逻辑总共分三步操作:
- 初始化
- 注册
- 绑定端口
首先看下启动过程的主干逻辑,然后再具体分析每一步操作的具体逻辑:
|
|
|
|
首先初始化NioServerSocketChannel并注册到bossGroup的eventLoop上,当NioServerSocketChannel已经执行完成注册操作,则直接进行端口绑定操作,否则添加Listener当执行完注册操作后再回调Listener进行端口绑定操作。
初始化NioServerSocketChannel并注册到bossGroup的eventLoop上
|
|
创建并初始化NioServerSocketChannel,然后将其注册到bossGroup的eventLoop上去,并返回注册操作的结果。
初始化
|
|
ServerBootstrapAcceptor主要用于接收TCP连接后初始化并注册NioSocketChannel到workGroup
|
|
Channel关心的网络事件SelectionKey.OP_READ
或者SelectionKey.OP_ACCEPT
发生都会触发read事件,进而调用责任链上ChannelHandler的channelRead相关逻辑,此处是因为SelectionKey.OP_ACCEPT
事件导致的ServerBootstrapAcceptor的channelRead事件被触发。这里主要是用于accept到连接后,对新建的NioSocketChannel进行属性设置并注册到workGroup线程组。
注册
注册NioServerSocketChannel,从bossGroup选择一个eventLoop线程,将NioServerSocketChannel注册到该eventLoop的selector上,通过channel获取unsafe,进而操作底层NIO的api进行注册操作
|
|
unsafe的register方法,判断当前线程是否是对应channel的eventLoop线程来决定是直接执行register0还是封装一个task交由对应的eventLoop来执行register0
|
|
调用底层NIO的api执行注册操作
|
|
绑定端口
提交注册后回到doBind端口绑定方法,当NioServerSocketChannel已经执行完成注册操作,则直接进行端口绑定操作,否则添加Listener当执行完注册操作后再回调Listener进行端口绑定操作,绑定操作需要操作channel,所以需要封装成task任务交由channel对应的eventLoop线程执行其bind方法
|
|
|
|
为了防止并发操作channel,需要由channel对应的eventLoop线程执行bind操作,此处将bind操作封装成task任务交由对应的eventLoop线程执行bind操作。
从责任链中获取ChannelOutboundHandler执行bind方法
|
|
|
|
绑定需要用的ChannelOutboundHandler是责任链的头部ChannelHandler:HeadContext
|
|
最终调用unsafe的bind方法
|
|
doBind获得底层NIO原生的ServerSocketChannel进行绑定端口操作
|
|
绑定完成后如果绑定成功则触发fireChannelActive方法,通过责任链会调用责任链的头部HeadContext处理,主要用于设置channel需要监听的操作位
|
|
最终调用unsafe的方法操作底层NIO的原生api做处理
|
|
在这里根据当前channel类型设置相应的监听位,此处处理的是NioServerSocketChannel,所以最终会设置SelectionKey.OP_ACCEPT
监听位
|
|
至此,ServerBootstrap服务端启动部分源码已经分析完成。