Netty传输数据传输API

网络应用程序一个很重要的工作是传输数据。传输数据的过程不一样取决是使用哪种交通工具,但是传输的方式是一样的:都是以字节码传输。Java 开发网络程序传输数据的过程和方式是被抽象了的,我们不需要关注底层接口,只需要使用 Java API 或其他网络框架如 Netty 就能达到传输数据的目的。发送数据和接收数据都是字节码。Nothingmore,nothing less。

Netty传输API 
传输 API 的核心是 Channel 接口,它用于所有出站的操作。Channel 接口的类层次结构如下: 
这里写图片描述

如上图所示,每个 Channel 都会分配一个 ChannelPipeline 和 ChannelConfig。 
ChannelConfig 负责设置并存储配置,并允许在运行期间更新它们。传输一般有特定的配置设置,只作用于传输,没有其他的实现。ChannelPipeline 容纳了使用的 ChannelHandler实例,这些 ChannelHandler 将处理通道传递的“入站”和“出站”数据。 
ChannelHandler 的实现允许你改变数据状态和传输数据,ChannelHandler 是 Netty 的重点概念。

现在我们可以使用 ChannelHandler 做下面一些事情:

  • 传输数据时,将数据从一种格式转换到另一种格式
  • 异常通知
  • Channel 变为有效或无效时获得通知
  • Channel 被注册或从 EventLoop 中注销时获得通知
  • 通知用户特定事件

这些 ChannelHandler 实例添加到 ChannelPipeline 中,在 ChannelPipeline 中按顺序逐个执行。它类似于一个链条。 
ChannelPipeline 实现了拦截过滤器模式, 这意味着我们连接不同的 ChannelHandler来拦截并处理经过 ChannelPipeline 的数据或事件。可以把 ChannelPipeline 想象成 UNIX管道,它允许不同的命令链(ChannelHandler 相当于命令)。你还可以在运行时根据需要添加 ChannelHandler 实例到 ChannelPipeline 或从 ChannelPipeline 中删除,这能帮助我们构建高度灵活的 Netty 程序。此外,访问指定的 ChannelPipeline 和 ChannelConfig,你能在 Channel 自身上进行操作。Channel 提供了很多方法,如下列表:

  • eventLoop(),返回分配给 Channel 的 EventLoop
  • pipeline(),返回分配给 Channel 的 ChannelPipeline
  • isActive(),返回 Channel 是否激活,已激活说明与远程连接对等
  • localAddress(),返回已绑定的本地 SocketAddress
  • remoteAddress(),返回已绑定的远程 SocketAddress
  • write(),写数据到远程客户端,数据通过 ChannelPipeline 传输过去

Netty 包含的传输实现

Netty 自带了一些传输协议的实现,虽然没有支持所有的传输协议,但是其自带的已足够我们来使用。Netty 应用程序的传输协议依赖于底层协议,本节我们将学习 Netty 中的传输协议。

Netty 中的传输方式有如下几种:

  • NIO,io.netty.channel.socket.nio,基于 java.nio.channels 
    的工具包,使用选择器作为基础的方法。
  • OIO,io.netty.channel.socket.oio,基于 java.net 的工具包,使用阻塞流。
  • Local,io.netty.channel.local,用来在虚拟机之间本地通信。
  • Embedded,io.netty.channel.embedded,嵌入传输,它允许在没有真正网络的运输中使用 ChannelHandler,可以非常有用的来测试 ChannelHandler 的实现。

NIO - Nonblocking I/O

NIO 传输是目前最常用的方式, 它通过使用选择器提供了完全异步的方式操作所有的I/O,NIO 从 Java 1.4 才被提供。NIO 中,我们可以注册一个通道或获得某个通道的改变的状态,通道状态有下面几种改变:

  • 一个新的 Channel 被接受并已准备好
  • Channel 连接完成
  • Channel 中有数据并已准备好读取
  • Channel 发送数据出去

处理完改变的状态后需重新设置他们的状态,用一个线程来检查是否有已准备好的Channel,如果有则执行相关事件。在这里可能只同时一个注册的事件而忽略其他的。选择器所支持的操作在 SelectionKey 中定义,具体如下:

  • OP_ACCEPT,有新连接时得到通知
  • OP_CONNECT,连接完成后得到通知
  • OP_READ,准备好读取数据时得到通知
  • OP_WRITE,写入数据到通道时得到通知

Netty 中的 NIO 传输就是基于这样的模型来接收和发送数据,通过封装将自己的接口提供给用户使用,这完全隐藏了内部实现。如前面所说,Netty 隐藏内部的实现细节,将抽象出来的 API 暴露出来供使用,下面是处理流程图: 
这里写图片描述 
NIO 在处理过程也会有一定的延迟,若连接数不大的话,延迟一般在毫秒级,但是其吞吐量依然比 OIO 模式的要高。Netty 中的 NIO 传输是“zero-file-copy”,也就是零文件复制,这种机制可以让程序速度更快, 更高效的从文件系统中传输内容, 零复制就是我们的应用程序不会将发送的数据先复制到 JVM 堆栈在进行处理,而是直接从内核空间操作。接下来我 
们将讨论 OIO 传输,它是阻塞的。

OIO - Old blocking I/O

OIO 就是 java 中提供的 Socket 接口,java 最开始只提供了阻塞的 Socket,阻塞会导致程序性能低。下面是 OIO的处理流程图

Local - In VM transport

Netty 包含了本地传输,这个传输实现使用相同的 API 用于虚拟机之间的通信,传输是完全异步的。 每个 Channel 使用唯一的 SocketAddress, 客户端通过使用 SocketAddress进行连接,在服务器会被注册为长期运行,一旦通道关闭,它会自动注销,客户端无法再使用它。 连接到本地传输服务器的行为与其他的传输实现几乎是相同的, 需要注意的一个重点是只能在本地的服务器和客户端上使用它们。Local 未绑定任何 Socket,值提供 JVM 进程之间的通信。

Embedded transport

Netty 还包括嵌入传输, 与之前讲述的其他传输实现比较, 它是不是一个真的传输呢?若不是一个真的传输,我们用它可以做什么呢?Embedded transport 允许更容易的使用不同的 ChannelHandler 之间的交互,这也更容易嵌入到其他的 ChannelHandler 实例并像一个辅助类一样使用它们。它一般用来测试特定的 ChannelHandler 实现,也可以在ChannelHandler 中重新使用一些 ChannelHandler 来进行扩展,为了实现这样的目的,它 自带了一个具体的 Channel 实现,即:EmbeddedChannel。

每种传输的使用时机

  • OIO,在低连接数、需要低延迟时、阻塞时使用
  • NIO,在高连接数时使用
  • Local,在同一个 JVM 内通信时使用
  • Embedded,测试 ChannelHandler 时使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值