Netty权威指南(三)
11 服务端创建
11.1 Netty服务端创建源码分析
11.1.1 Netty服务端创建时序图

- 创建ServerBootstrap实例。ServerBootstrap是Netty服务端的启动辅助类,它提供了一系列的方法用于设置服务端启动相关参数。
- 设置并绑定Reactor线程池,Netty的Reactor线程池是EventLoopGroup它实际就是EventLoop的数组。EventLoop的职责就是处理所有注册到本线程多路复用器Selector上的Channel,Selector的轮询操作由绑定EventLoop线程run方法驱动,在一个循环体内循环执行。EventLoop的职责不仅仅是处理网络I/O事件,用户自定义的Task的定时任务Tak也统一由EventLoop负责处理,实现线程模型统一。
- 设置并绑定服务端Channel。作为NIO服务端需要创建ServerSocketChannel,Netty对原生的NIo类库进行了封装,对应实现是NioServerSocketChannel。
public ServerBootstrap channel(Class<? extends ServerChannel> channelClass) {
if (channelClass == null) {
throw new NullPointerException("channelClass");
} else {
return this.channelFactory(new ServerBootstrap.ServerBootstrapChannelFactory(channelClass));
}
}
- 链路建立的时候创建并初始化ChannelPipeline.ChannelPipeline并不是NIO服务端必须的,它本质就是一个负责处理网络事件的职责链,负责管理和执行ChannelHandler。网络事件以事件流的形式ChannelPipeline中流转,由ChannelPipeline根据ChannelHandler的执行策略调度ChannelHandler的执行。网络事件一般有:链路注册、链路激活、链路断开、接收请求、请求消息接收并处理完成、发送应答消息、链路异常、自定义事件。
- 初始化ChannelPipeline完成之后,添加并设置ChannelHandler。ChannelHandler是Netty提供给用户定制和扩展的关键接口。利用ChannelHandler用户可以完成大多数的功能定制。比如
- 系统编解码框架-BtyeToMessageCodec
- 通用基于长度的半包解码器-LengthFieldBasedFrameDecoder
- 码流日志打印-LoggingHandler
- SSL安全认证-SslHandler
- 链路空闲检测-IdleStateHandler
- 流量整形-ChannelTrafficShapingHandler
- Base64编解码-Base64Decoder和Base64Encoder
创建和添加ChannelHandler代码示例
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws IOException {
ch.pipeline().addLast(
new NettyMessageDecoder(1024 * 1024, 4, 4));
ch.pipeline().addLast(new NettyMessageEncoder());
ch.pipeline().addLast("readTimeoutHandler",
new ReadTimeoutHandler(50));
ch.pipeline().addLast(new LoginAuthRespHandler());
ch.pipeline().addLast("HeartBeatHandler",
new HeartBeatRespHandler());
}
});
- 绑定并启动监听端口。在绑定监听端口之前系统会做一系列的初始化和检测工作,完成之后,会启动监听端口,并将ServerSocketChannel注册到Selector上监听客户端连接。
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = this.initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
} else {
final Object promise;
if (regFuture.isDone()) {
promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, (ChannelPromise)promise);
} else {
promise = new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE);
regFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
AbstractBootstrap.doBind0(regFuture, channel, localAddress, (ChannelPromise)promise);
}
});
}
return (ChannelFuture)promise;
}
}
- Selector轮询。由Reactor线程NioeventLoop负责调度和执行Selector轮询操作,选择准备就绪到Channel集合。
- 当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法,最终调度并执行ChannelHandler。
- 执行Netty系统ChannelHandler和用户添加定制的ChannelHandler。ChannelPipeline根据网络事件类型,调度并执行ChannelHandler。
public ChannelHandlerContext fireChannelRead(Object msg) {
DefaultChannelHandlerContext next = this.findContextInbound(64);
next.invoker.invokeChannelRead(next, msg);
return this;
}
11.1.2 Netty服务端创建源码分析
首先通过构造函数创建ServerBootstrap实例,随后,通常会创建两个EventLoopGroup。
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
NioEventLoopGroup实际就是Reactor线程池,负责调度和执行客户端的接入、网络读写事件的处理、用户自定义任务和定时任务的执行。通过ServerBootstrao的group方法将两个EventLoopGroup实例传入。
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
} else if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
} else {
this.childGroup = childGroup;
return this;
}
}
其中父NioEventLoopGroup被传入了父
LIKECAT
一条小咸鱼