本文共 2620 字,大约阅读时间需要 8 分钟。
传输 API 的核心是 interface Channel,它被用于所有的 I/O 操作。Channel 类的层次结构如图所示:
如图所示,每个 Channel 都将会被分配一个 ChannelPipeline 和 ChannelConfig。 ChannelConfig 包含了该 Channel 的所有配置设置,并且支持热更新。由于特定的传输可能 具有独特的设置,所以它可能会实现一个 ChannelConfig 的子类型。(请参考 ChannelConfig 实现对应的 Javadoc。)
由于 Channel 是独一无二的,所以为了保证顺序将 Channel 声明为 java.lang. Comparable 的一个子接口。因此,如果两个不同的 Channel 实例都返回了相同的散列码,那 么 AbstractChannel 中的 compareTo()方法的实现将会抛出一个 Error。
ChannelPipeline 持有所有将应用于入站和出站数据以及事件的 ChannelHandler 实 例,这些 ChannelHandler 实现了应用程序用于处理状态变化以及数据处理的逻辑。
ChannelHandler 的典型用途包括:你也可以根据需要通过添加或者移除ChannelHandler实例来修改ChannelPipeline。
通过利用Netty的这项能力可以构建出高度灵活的应用程序。例如,每当STARTTLS1协议被请
求 时 , 你 可 以 简 单 地 通 过 向ChannelPipeline添加一 个 适 当 的ChannelHandler (SslHandler)来按需地支持STARTTLS协议。Netty所提供的传输:
NIO 提供了一个所有 I/O 操作的全异步的实现。它利用了自 NIO 子系统被引入 JDK 1.4 时便 可用的基于选择器的 API。
选择器背后的基本概念是充当一个注册表,在那里你将可以请求在 Channel 的状态发生变 化时得到通知。可能的状态变化有:出响应之后,选择器将会被重置,并将重复这个过程。
下表中的常量值代表了由class java.nio.channels.SelectionKey
定义的位模式。 这些位模式可以组合起来定义一组应用程序正在请求通知的状态变化集。 Netty为Linux提供了一组NIO API,其以一种和它本身的设计更加一致的方式使用epoll,并 且以一种更加轻量的方式使用中断。1如果你的应用程序旨在运行于Linux系统,那么请考虑利用 这个版本的传输;你将发现在高负载下它的性能要优于JDK的NIO实现。
它的用法也是简单直接的。如果要使用 epoll 替代 NIO,只需要将 NioEventLoopGroup 替换为 EpollEventLoopGroup,并且将 NioServerSocketChannel.class 替换为 EpollServerSocketChannel.class 即可。
Netty 的 OIO 传输实现代表了一种折中:它可以通过常规的传输 API 使用,但是由于它 是建立在 java.net 包的阻塞实现之上的,所以它不是异步的。但是,它仍然非常适合于某 些用途。
例如,你可能需要移植使用了一些进行阻塞调用的库(如JDBC2)的遗留代码,而将逻辑转 换为非阻塞的可能也是不切实际的。相反,你可以在短期内使用Netty的OIO传输,然后再将你的 代码移植到纯粹的异步传输上。
在 java.net API 中,你通常会有一个用来接受到达正在监听的 ServerSocket 的新连 接的线程。会创建一个新的和远程节点进行交互的套接字,并且会分配一个新的用于处理相应通 信流量的线程。这是必需的,因为某个指定套接字上的任何 I/O 操作在任意的时间点上都可能会 阻塞。使用单个线程来处理多个套接字,很容易导致一个套接字上的阻塞操作也捆绑了所有其他 的套接字。
有了这个背景,你可能会想,Netty是如何能够使用和用于异步传输相同的API来支持OIO的呢。 答案就是,Netty利用了SO_TIMEOUT这个Socket标志,它指定了等待一个I/O操作完成的最大毫秒 数。如果操作在指定的时间间隔内没有完成,则将会抛出一个SocketTimeout Exception。Netty 将捕获这个异常并继续处理循环。在EventLoop下一次运行时,它将再次尝试。这实际上也是 类似于Netty这样的异步框架能够支持OIO的唯一方式:
Netty 提供了一个 Local 传输,用于在同一个 JVM 中运行的客户端和服务器程序之间的异步 通信。同样,这个传输也支持对于所有 Netty 传输实现都共同的 API。
在这个传输中,和服务器 Channel 相关联的 SocketAddress 并没有绑定物理网络地址; 相反,只要服务器还在运行,它就会被存储在注册表里,并在 Channel 关闭时注销。因为这个 传输并不接受真正的网络流量,所以它并不能够和其他传输实现进行互操作。因此,客户端希望 连接到(在同一个 JVM 中)使用了这个传输的服务器端时也必须使用它。除了这个限制,它的 使用方式和其他的传输一模一样。
Netty 提供了一种额外的传输,使得你可以将一组 ChannelHandler 作为帮助器类嵌入到 其他的 ChannelHandler 内部。通过这种方式,你将可以扩展一个 ChannelHandler 的功能, 而又不需要修改其内部代码。
转载地址:http://tlpqb.baihongyu.com/