Netty是什么?
Netty是一个高性能、异步事件驱动的网络应用骨架。基于Netty,可以快速开发和部署高性能、高可用的网络服务端和客户端应用 简单来说,它是一个网络应用框架,帮你解决面向网络开发的三个问题: 1.面向网络IO的读写,如TC的socket连接 2.应用层协议编解码,如HTTP协议 3.高并发架构
简要
本文从Netty(版本4.1.42)服务端的建立入手,简要列出流程,后续继续学习再深入探讨。
Netty的服务端
Netty服务端创建时序图:

1.创建ServerBootStrap实例。
ServerBootStrap是Netty服务端的启动辅助类,提供了一系列的方法用于设置服务端启动的相关参数。底层通过门面模式对各种能力进行抽象和封装,尽量不需要用户跟过多的API打交道,降低了开发难度。
其次,ServerBootStrap只有一个无参的构造函数,作为启动辅助类需要设置很多参数串联许多组件,因此引入了Builder模式,避免了过多的参数,也容易扩展。
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
ObjectUtil.checkNotNull(childGroup, "childGroup");
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
//返回对象本身 (Builder模式体现)
return this;
}
2.绑定Reactor线程池。
Netty的Reactor线程池就是EventLoopGroup,它实际就是EventLoop的数组。EventLoop的职责是负责处理所有注册到本线程多路复用器Selector上的Channel,Selector的轮询操作由绑定的EventLoop线程run方法驱动,在一个循环体内循环执行。值得说明的是,EventLoop不仅仅处理网络IO事件,用户自定义的Task和定时任务Task也统一由EventLoop负责处理,这样线程模型就实现了统一。从调度层面看,也不存在从EventLoop线程中再启动其它类型的线程用于异步执行另外的任务,这样就避免了多线程并发操作和锁竞争,提升了I/O处理和调度性能
Netty 自己内部实现了JDK提供的线程接口Executor来执行提交的任务,其执行线程任务相关的类的命名也都包含Executor方便识别。
//EventLoop所绑定的线程类SingleThreadEventLoop.java
//NioEventLoop.java 445行
@Override
protected void run() {
for (;;) {
//执行Selector轮询操作
}
}
//方法的调用者 SingleThreadEventExecutor.java 874行,重载了线程接口Executor的execute()方法
@Override
public void execute(Runnable task) {
//执行NioEventLoop.java中的run方法
}
3.设置并绑定服务端Channel
作为NIO服务端,需要创建ServerSocketChannel,Netty对原生的NIO类库进行了封装,对应实现是NioServerSocketChannel。对于用户而言,不需要关心服务端Channel的底层实现细节和工作原理,只需要指定具体使用哪种Channel即可。Netty的ServerBootStrap类方法channel()提供了用于指定Channel的类型。Netty通过工程类,利用反射创建NioServerSocketChannel对象。相关代码:
public B channel(Class<? extends C> channelClass) {
return channelFactory(new ReflectiveChannelFactory<C>(
ObjectUtil.checkNotNull(channelClass, "channelClass")
));
}
4.链路建立的时候创建并初始化ChannelPipeline。
ChannelPipeline并不是NIO服务端所必需的,它本质就是一个负责处理网络事件的责任链,负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转,由ChannelPipeline根据ChannelHandler的执行策略调度ChannelHandler的执行。
//AbstractChannel.java 106行
protected DefaultChannelPipeline newChannelPipeline() {
//初始化ChannelPipeline
return new DefaultChannelPipeline(this);
}
5.初始化ChannelPipeline完成之后,添加并设置ChannelHandler。
ChannelHandler是Netty提供给用户定制和扩展的关键接口。利用ChannelHandler用户可以完成大多数的功能定制,例如消息编解码、心跳、安全认证、TSL/SSL认证、流量控制等。Nettty同时也提供了大量的系统ChannelHandler供用户使用。添加ChannelHandler的实例:
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
//自定义的ChannelHandler需要继承ChannelInboundHandlerAdapter类
ch.pipeline().addLast(new ChatServerHandler());
}
});
6.绑定并启动监听端口。
在绑定监听端口之前系统会做一系列的初始化和检测工作,完成之后,会启动监听端口,并将ServerSocketChannel注册到Selector上监听客户端连接:
//AbstractBootStrap.java 259行
private ChannelFuture doBind(final SocketAddress localAddress) {
//初始化、检测...
}
7.Selector轮询。
由Reactor线程NioEventLoop负责调度和执行Selector轮询操作,选择准备就绪的Channel集合:
//NioEventLoop.java 792行
private void select(boolean oldWakenUp) throws IOException {
//...
}
8.网络事件通知
当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法,最终调度并执行ChannelHandler。
//入口 NioEventLoop.java 550行
private void processSelectedKeys() {
//处理准备就绪的key
}
9.执行Netty系统ChannelHandler和用户添加定制的ChannelHandler。
//DefaultChannelPipeline.java 930行
@Override
public final ChannelPipeline fireChannelRead(Object msg) {
//调度执行相应的Channelhandler
}
参考
有需要简单了解Netty面貌的童鞋可参考 这可能是目前最透彻的Netty原理架构解析
关于Netty的demo可参考Introducton GitBook
《Netty 权威指南》第二版