这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
一、传输API
传输API的核心是interface Channel,它被用于所有的I/O操作。Channel类的层次结构如下图所示:
每个Channel都将会被分配一个ChannelPipeline和ChannelConfig。ChannelConfig包含了该Channel的所有配置设置,并且支持热更新。
由于Channel是独一无二的,所以为了保证顺序将Channel声明为java.lang.Comparable的一个子接口。因些,如果两个不同的Channel实例都返回了相同的散列码,那么AbstractChannel中的CompareTo()方法的实现将会抛出一个Error。
ChannelPipeline持有所有将应用于入站和出站数据以及事件的ChannelHandler实现,这些ChannelHandler实现了应用程序用于处理状态变化以及数据处理的逻辑。
ChannelHandler的典型用途包括:
- 将数据从一种格式转换为另一种格式;
- 提供异常的通知;
- 提供Channel变为活动的或者非活动的通知;
- 提供当Channel注册到EventLoop或者从EventLoop注销时的通知;
- 提供有关用户自定义事件的通知 Netty的Channel实现是线程安全的,因此可以存储一个到Channel的引用,并且每当你需要向远程节点写数据时,都可以使用它,即使当时许多线程都在使用它。
二、内置的传输
Netty内置了一些可开箱即用的传输,但它们并不是所有的传输协议都支持,所以必须选择一个和你的应用程序所使用的协议相容的传输。下表显示所有的Netty提供的传输。
| 名 称 | 包 | 描 述 |
|---|---|---|
| NIO | io.netty.channel.socket.nio | 使用java.nio.channels包作为基础——基于选择器的方式 |
| Epoll | io.netty.channel.epoll | 由JNI驱动的epoll()和非阻塞IO。这个传输支持只有Linux上可用的多种特性,如SO_REUSEPORT,比NIO传输更快,而且是完全非阻塞的 |
| NIO | io.netty.channel.socket.nio | 使用java.nio.channels包作为基础——基于选择器的方式 |
| OIO | io.netty.channel.socket.oio | 使用java.net包作为基础——使用阻塞流 |
| Local | io.netty.channel.local | 可以在VM内部通过管道进行通信的本地传输 |
| Embedded | io.netty.channel.embedded | Embedded传输,允许使用ChannelHandler而又不需要一个真正的基于网络的传输。这在测试你的ChannelHandler实现时非常有用 |
2.1 NIO——非阻塞I/O
NIO提供了一个所有I/O操作的全异步的实现。它利用了自NIO子系统被引入JDK1.4时便可用的基于选择器的API。
选择器背后的基本概念是充当一个注册表,在那里你将可以请求在Channel的状态发生变化时得到通知。可能的状态变化有 :
- 新的Channel已被接受并且就绪(对应的状态集OP_ACCEPT)
- Channel连接已经完成(对应的状态集OP_CONNECT)
- Channel有已经就绪的可供读取的数据;(对应的状态集OP_READ)
- Channel可用于写数据(对应的状态集OP_WRITE) 选择器运行在一个检查状态变化并对其做出相应响应的线程上,在应用程序对状态的改变做出响应之后,选择器将会被重置,并将重复这个过程。
对于所有Netty的传输实现都共有的用户级别API完全地隐藏了这些NIO的内部细节。下图展示了该处理流程。
2.2 Epoll——用于Linux的本地非阻塞传输
Netyy的NIO传输基于Java提供的异步/非阻塞网络编程的通用抽象。虽然这保证了Netty的非阻塞API可以在任何平台上使用,但它也包含了相应的限制,因为JDK为了在所有系统上提供相同的功能,必须做出妥协。
Linux作为高性能网络编程的平台,其重要性与日俱增,这催生了大量先进特性的开发,其中包括epoll—— 一个高度可扩展的I/O事件通知特性。这个API自Linux内核版本2.5.44(2002)被引入,提供了比旧的POSIX select和poll系统调用更好的性能,同时现在也是Linux上非阻塞网络编程的事实标准。Linux JDK NIO API使用了这些epoll调用。如果你的应用程序旨在运行于Linux系统,那么请考虑利用这个版本的传输;你将发现在高负载下它的性能要优于JDK的NIO实现。
2.3 OIO——旧的阻塞I/O
Netty的OIO传输实现代表了一种折中:它可以通过常规的传输API使用,但是由于它是建立在java.net包的阻塞实现之上的,所以它不是异步的。但是,它仍然非常适合于某些用途。 下图是NettyOIO传输的流程:
2.4 用于JVM内部通信的Local传输
Netty提供了一个Local传输,用于在同一个JVM中运行的客户端和服务器程序之间的异步通信。同样,这个传输也支持对于所有Netty传输实现都共同的API。
2.5 Embedded传输
Netty提供了一种额外的传输,使得你可以将一组ChannelHandler作为帮助器类嵌入到其他的ChannelHandler内部。通过这种方式,你将可以扩展一个ChannelHandler的功能,而又不需要修改其内部代码。