概览
Netty是一个当前比较流行的高可用java 网络开源框架,最新的版本是Netty 4。本文主要介绍Netty实现原理和设计。
NIO模式
在介绍NIO模式前,需要说明一下BIO模式它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞。由于IO的效率较低,会严重阻塞CPU的调度。
NIO 是 多路复用的、同步非阻塞 IO ,Java提供了 Channel、Selector、Buffer 等新的抽象,提供了更接近操作系统底层高性能的数据操作方式,解决了BIO模式中影响CPU效率的问题。
Channel
Channel是Netty中的核心概念,承载网络通信的主体,负责同对端进行网络通信、注册和数据操作等功能,下图为Channel的核心类。
1 Channel:和Java Nio中的Channel同名,是Netty对网络底层读写和连接的抽象。
AbstractChannel: 是Channel的抽象实现类,抽象出了parent,id,unsafe,pipeline等概念。
2 AbstractNioChannel:封装Java NIO,通过Selector选择器进行IO事件的监听,拥有SelectionKey,readInterestOp等NIO的属性,这是在这个类的构造函数中设置了非阻塞模式。
3 AbstractNioByteChannel此抽象类开始的分支中的类都是关于客户端的Channel,AbstractNioMessageChannel此抽象类开始的分支中的类都是关于服务端的Channel,前者和后者都继承自AbstractNioChannel
可以通过Channel获取如下信息.
1 Channel的当前状态(如,是否连接,是否打开)
2 Channel的配置参数,如buffer的size
3 支持的I/O操作
4 处理所有I/O事件的ChannelPipeline和与通道相关的请求
每个channel对应一个网络连接,对不同的连接需要实现不同的channel
ChannelHandler
ChannelHandler是Netty基本接口的关系,如图Netty中所有编解码器均实现ChannelHandler接口。在ChannelPipeline中会将编码器和解码器组成入站和出站队列。该过程使用的是责任链模式。
ChannelInboundHandler接口处理所有入站操作,所有编码器均需实现该接口。当接收数据时数据在入站队列中处理并传递。ChannelOutboundHandler接口处理所有出站操作,所有解码器均需实现该接口。当发送数据时,在出站队列中处理并传递。
了解如上接口可以帮助理解Netty网络数据的处理流程,但实际使用中,我们并不会直接接触以上接口。下面介绍的是实际使用中常用的编解码类。
ByteToMessageDecoder
MessageToMessageDecoder
MessageToByteEncoder
MessageToMessageEncoder
ByteBuffer
Netty中引入了ByteBuf,它相对于ByteBuffer来说,带来了很多便捷性和创新的地方,使得程序员更简单得进行网络编程,源码中的继承关系如下图所示
ByteBuf 是一个已经经过优化的很好使用的数据容器,字节数据可以有效的被添加到 ByteBuf 中或者也可以从 ByteBuf 中直接获取数据。ByteBuf中有两个索引:一个用来读,一个用来写。这两个索引达到了便于操作的目的。我们可以按顺序的读取数据,也可以通过调整读取数据的索引或者直接将读取位置索引作为参数传递给get方法来重复读取数据。