Channel
:Socket,对应一个链接。java
bind()
、 connect()
、 read()
、 write()
等,就是对 Java 中实现的 Socket 进行必定层次的封装。EventLoop
:控制流、多线程处理、并发。数组
EventLoopGroup
中包含一个或多个 EventLoop
。EventLoop
在它的生命周期内只和一个 Thread
绑定。EventLoop
处理的 I/O 事件都在它专有的 Thread
上被处理。Channel
在它的生命周期内只注册于一个 EventLoop
。EventLoop
可能会被分配给一个或多个 Channel
。ChannelFuture
:异步通知。缓存
Future
。可以在以后的某个时间点肯定结果,对 Future
添加 Listener
注册回调,再操做完成后通知执行相应的回调。ChannelHandler
:在 Channel
上发生事件的处理器。服务器
ChannelInboundHandler
:接收入站事件和数据。ChannelOutboundHandler
:数据出站处理器。ChannelPipeline
: ChannelHandler
链的容器。网络
ChannelPipeline
就是一些 ChannelHandler
的编排顺序,每一个 ChannelHandler
接收事件,执行所实现的处理逻辑,完毕后交给下个一个 ChannelHandler
。ChannelPipeline
的编排,在必定次序下调用 ChannelOutboundHandler
。响应的接收服务器发来数据就是入站的,在一个 ChannelPipeline
按顺序调用 ChannelInboundHandler
。ChannelPipeline
中从头部开始按顺序调用 ChannnelInboundHandler
。从客户端发送数据到服务器则是从 ChannelPipeline 的尾部开始执行,直到发送到网络上。
ChannelHandlerContext
:表明了 ChannelHandler
和 ChannelPipeline
之间的绑定。多线程
Channel
。两种发送消息的方式:并发
Channel
中:消息从 ChannelPipeline
的尾部开始流动。ChannelHandler
相关联的 ChannelHandlerContext
对象中: 消息从 ChannelPipeline
的下一个ChannelHandler
开始流动。Channel
都会被分配一个
ChannelPipeline
和
ChannelConfig
。
ChannelConfig
:对应 Channel
的配置设置,支持热更新。ChannelPipeline
: 持有全部将应用于入站和出站数据以及事件的 ChannelHandler
实例,这些 ChannelHandler
实现了应用程序用于处理状态变化以及数据处理的逻辑。名称 | 包 | 描述 |
---|---|---|
NIO | io.netty.channel.socket.nio | 使用 java.nio.channels 包做为基础——基于选择器(select) |
Epoll | io.netty.channel.epoll | 由 JNI 驱动的 epoll() 和非阻塞 IO。这个传输支持只有在Linux上可用的多种特性,如 SO_REUSEPORT,比NIO 传输更快,并且是彻底非阻塞的 |
OIO | io.netty.channel.socket.oio | 使用 java.net 包做为基础——使用阻塞流 |
Local | io.netty.channel.local | 能够在 VM 内部经过管道进行通讯的本地传输 |
Embedded | io.netty.channel.embedded | Embedded 传输,容许使用 ChannelHandler 而又不须要一个真正的基于网络的传输。这在测试 ChannelHandler 实现时很是有用 |
Channel
在选择器(Selector
)上注册,当 Selector
调用 select()
的时候是阻塞的,直到已经注册的 Channel
中有相应的事件发生。事件 | 描述 |
---|---|
OP_ACCEPT | 请求在接受新链接并建立 Channel 时得到通知 |
OP_CONNECT | 请求在创建一个链接时得到通知 |
OP_READ | 请求当数据已经就绪,能够从 Channel 中读取时得到通知 |
OP_WRITE | 请求当能够向 Channel 中写更多的数据时得到通知。这处理了套接字缓冲区被彻底填满时的状况,这种状况一般发生在数据的发送速度比远程节点可处理的速度更快的时候 |
处理模型: 异步
Epoll NIO 是基于 Select 的,那么 Epoll 如其名,则是基于 Linux 的 epoll 。好处不言而喻,提供比旧的 select 和 poll 更好的性能。 对应的则是 EpollEventLoopGroup
和 EpollServerSocketChannel
。socket
OIO 创建在 java.net
包下,不是异步的。可以经过设置 SO_TIMEOUT
来在单线程中处理多个链接。函数
Embedded Embedded 提供了能够将一组 ChannelHandler
做为帮助器嵌入到其余的 ChannelHandler
内部。这样能够扩展一个 ChannelHandler
的功能,但又不须要修改其内部代码。
维护了两个不一样的索引:readerIndex
和 writerIndex
,一个用于读取,一个用于写入。当从 ByteBuf
读取时,readerIndex
递增。一样当从 ByteBuf
写入时, writerIndex
递增。 若是 readerIndex
递增到和 writerIndex
相同的值,那么到达“可读取数据的末尾”,这时再进行读取则会像读取超出数组末尾的数据同样,抛出 IndexOutOfBoundsException
。 另外,名称以 read 或者 write 开头的 ByteBuf
方法会推动相应的索引值,而以 set 或者 get 开头的方法则不会(这样只是在相应的索引值上进行操做)。
在弄清楚 ByteBuf
的使用模式以前,应该理解 Java 中的直接缓冲区和非直接缓冲区:
直接缓冲区:缓冲区创建在物理内存中,能够提升效率。
非直接缓冲区:缓冲区创建在 JVM 的内存中。
堆缓冲区(backing 模式) ByteBuf
数据存储在 JVM 的堆空间(非直接缓冲区)中。这种模式也被称为“支撑数组(backing array)”,可以在没有使用池化的的状况下提供快速的分配和释放。
直接缓冲区(direct 模式) 经过本地调用分配内存,直接分配的是物理内存。
复合缓冲区 为多个 ByteBuf
提供一个聚合视图。
CompositeByteBuf
:可以提供将多个缓冲区(每一个 ByteBuf
能够是 backing 模式或者 direct 模式)表示为单个合并缓冲区的虚拟表示。ByteBuf
的索引是从 0 开始到 capacity() - 1。 获取每一个字节的方法则是:byte getByte(int i);
这样倒不会改变 readerIndex
和 writerIndex
的值。 固然能够经过:ByteBuf readerIndex(int index)
和ByteBuf writerIndex(int index)
来手动移动读取/写入索引值。discardReadBytes()
方法,能够丢弃已经被读过的字节以回收空间。是的,调用discardReadBytes()
能够确保可写分段的最大化,可是有可能致使内存复制(可读字节会移动到缓冲区的开始位置)。一样的可丢弃字节空间也只是相应的更改了 writerIndex
的值,并不会保证空间中值的擦写。ByteBuf
的可读字节分段(CONTENT)存储了实际数据。任何名称以 read 或者 skip 开头的操做都将检索或者跳过位于当前 readerIndex
的数据,而且将它增长已读字节数。InputStream
定义了mark(int readlimit)
和reset()
方法,来标记流中指定位置,以及重置。在 ByteBuf
中也有相应的方法来标记和重置 ByteBuf
中的 readerIndex
和 writerIndex
:
markReaderIndex()
markWriterIndex()
resetReaderIndex()
resetWriterIndex()
还有clear()
方法只是重置索引,且不会复制内存。indexOf()
方法。 或者使用ByteProcessor
类。duplicate()
slice()
slice(int , int)
Unpooled.unmodifiableBuffer(...)
order(ByteOrder)
readSlice(int)
以上每一个方法都会返回一个新的ByteBuf
实例,具备本身的读索引、写索引和标记索引。可是内部存储是共享的。因此若是修改了它的内容,也同时修改了其对应的源实例。 若是要深拷贝得到真实副本,使用copy()
或者copy(int ,int)
函数。get()
和set()
操做,从给定的索引值开始,且保持索引值不变。read()
和write()
操做,从给定的索引开始,且会根据以及访问过的字节数堆索引进行调整。 get()
方法:
set()
方法:
read()
方法:
write()
方法:
ByteBufAllocator
接口 ByteBufAllocator
的方法:
Channel
或者ChannelHandlerContext
获取到一个ByteBufAllocator
的引用。 Netty提供了两种ByteBufAllocator
的实现:PooledByteBufAllocator
:池化了ByteBuf
的实例以提升性能而且最大限度的减小内存碎片。UnpooledByteBufAllocator
:不池化ByteBuf
实例,可是每次被调用时会返回一个新的实例。Unpooled
缓冲区 没法获取到ByteBufAllocator
的引用时,有一个简单的Unpooled
工具类,提供静态的辅助方法来建立未池化的ByteBuf
实例。
ByteBufUtil
类 这个类提供了用于操做ByteBuf
的静态辅助方法。