ServerBootstrap 的 option 与 childOption 分别有什么作用
服务端IO通道如何绑定事件链。
ServerBootstrap 的 handler 方法与 childHandler 方法的区别又是什么?
childHandler中的方法在服务端bind方法时会被调用吗?
[](()1、Netty服务端启动示例
基于Netty的使用示例如下:
代码@1:创建主从多Reactor线程模型的Boss线程组,通常只需要设置一个线程,用于监听客户端的连接请求(OP_ACCEPT)。
代码@2:创建主从多Reactor线程模型的Work线程组,即IO线程组,默认为CPU核数的两倍。
代码@3:创建Netty服务端启动工具类ServerBootstrap。
代码@4:调用group方法设置主从线程组。
代码@5:设置通道的类型,服务端NIO通道类型 NioServerSocketChannel。
代码@6:通过option方法为通道服务端通道选项。
代码@7:通过chiildOption方法为IO通道设置选项。
代码@8:通过ChannelInitializer添加自定义的ChannelHandler,通常包括编码解码器、业务Handler。
代码@9:调用管道的addLast添加自定义编码解码器。
代码@10:调用bind方法绑定到服务端指定接口,绑定完成后则在指点端口上监听客户端的连接。
服务端的核心流程入口为bind方法,接下来我们将详细分析其实现原理,继续体会NIO编程技巧。
[](()2、Netty服务端启动流程
通过跟踪其bind方法,最终将进入到AbstractBootstrap的doBind方法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210219234131283.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nL 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 mNzZG4ubmV0L3ByZXN0aWdlZGluZw==,size_16,color_FFFFFF,t_70)
其关键实现点:
代码@1:通过调用initAndRegister方法完成底层网络初始化与通道注册工作。
代码@2:如果初始化与注册工作已完成,则直接调用doBind0方法完成绑定操作。
代码@3:如果初始化与注册工作未完成,则通过regFuture(注册凭证)中添加监听器,等注册完成后再执行doBind0方法。
技巧提示:基于Future异步编程,在主线程中通过调用future.isDone方法判断异步方法是否已完成,如果未完成,通过在该凭证上添加监听器(事件回调),操作完成后执行回调逻辑。
从上面的方法来看服务端的绑定流程包含初始化与绑定两个子流程,接下来将分别深入探讨。
基于NIO编程,需要先创建通道,然后将其注册到事件选择器,这个过程由 AbstractBootstrap 的 initAndRegister 方法实现。
实现的关键点如下:
代码@1:创建NIO服务端通道实现类NioServerSocketChannel的实例。
代码@2:调用 init 方法初始化通道。
代码@3:将通道注册到事件轮询器EventLoopGroup
代码@4::如果通道已注册,但发生了错误则调用通道close方法回收相关资源,如果未注册成功,则强制清除通道占用的资源,特别是文件占用符。
关于通道的注册逻辑已经在[手把手教你如何编写一个NIO客户端](() 中已详细介绍,故接下来重点关注一下服务端通道的注册流程。
AbstractBootstrap 的 init 方法是一个抽象方法,具体有其子类实现:
服务端通道的初始化代码由ServerBootstrap的init方法。
Step1:首先将通过ServerBootstrap设置的选项与附加选项初始化到通道中。
Step2:init 方法的关键点:将 handler 方法设置的事件链,同时新增 ServerBootstrapAcceptor 事件处理方法加入到 NioServerSocketChannel 的事件链,但并没有把 childHandler 中添加的事件链添加到NioServerSocketChannel。