传输(Transport)

在网络中传递的数据总是具有相同的类型:字节。 这些字节流动的细节取决于网络传输,它是一个帮我们抽象 底层数据传输机制的概念,我们不需要关心字节流动的细节,只需要确保字节被可靠的接收和发送。

当我们使用Java网络编程时,可能会接触到多种不同的网络IO模型,如NIO,BIO(OIO: Old IO),AIO等,我们可能因为 使用这些不同的API而遇到问题。 Netty则为这些不同的IO模型实现了一个通用的API,我们使用这个通用的API比直接使用JDK提供的API要 简单的多,且避免了由于使用不同API而带来的问题,大大提高了代码的可读性。 在传输这一部分,我们将主要学习这个通用的API,以及它与JDK之间的对比。

传输API

传输API的核心是Channel(io.netty.Channel,而非java nio的Channel)接口,它被用于所有的IO操作。

Channel结构层次:

每个Channel都会被分配一个ChannelPipeline和ChannelConfig, ChannelConfig包含了该Channel的所有配置,并允许在运行期间更新它们。

ChannelPipeline在上面已经介绍过了,它存储了所有用于处理出站和入站数据的ChannelHandler, 我们可以在运行时根据自己的需求添加或删除ChannelPipeline中的ChannelHandler。

此外,Channel还有以下方法值得留意:

方法名 描述
eventLoop 返回当前Channel注册到的EventLoop
pipeline 返回分配给Channel的ChannelPipeline
isActive 判断当前Channel是活动的,如果是则返回true。 此处活动的意义依赖于底层的传输,如果底层传输是TCP Socket,那么客户端与服务端保持连接便是活动的;如果底层传输是UDP Datagram,那么Datagram传输被打开就是活动的。
localAddress 返回本地SocketAddress
remoteAddress 返回远程的SocketAddress
write 将数据写入远程主机,数据将会通过ChannelPipeline传输
flush 将之前写入的数据刷新到底层传输
writeFlush 等同于调用 write 写入数据后再调用 flush 刷新数据

Netty内置的传输

Netty内置了一些开箱即用的传输,我们上面介绍了传输的核心API是Channel,那么这些已经封装好的 传输也是基于Channel的。

Netty内置Channel接口层次:

名称 描述
NIO io.netty.channel.socket.nio NIO Channel基于java.nio.channels,其io模型为IO多路复用
Epoll io.netty.channel.epoll Epoll Channel基于操作系统的epoll函数,其io模型为IO多路复用,不过Epoll模型只支持在Linux上的多种特性,比NIO性能更好
KQueue io.netty.channel.kqueue KQueue 与 Epoll 相似,它主要被用于 FreeBSD 系统上,如Mac等
OIO(Old Io) io.netty.channel.socket.oio OIO Channel基于java.net包,其io模型是阻塞的,且此传输被Netty标记为deprecated,故不推荐使用,最好使用NIO / EPOLL / KQUEUE 等传输
Local io.netty.channel.local Local Channel 可以在VM虚拟机内部进行本地通信
Embedded io.netty.channel.embedded Embedded Channel允许在没有真正的网络传输中使用ChannelHandler,可以非常有用的测试ChannelHandler

零拷贝

理解零拷贝 零拷贝是Netty的重要特性之一,而究竟什么是零拷贝呢? WIKI中对其有如下定义:

“Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another.

从WIKI的定义中,我们看到“零拷贝”是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。而它通常是指计算机在网络上发送文件时,不需要将文件内容拷贝到用户空间(User Space)而直接在内核空间(Kernel Space)中传输到网络的方式。

Non-Zero Copy方式:

应用程序启动后,向内核发出read调用(用户态切换到内核态),操作系统收到调用请求后, 会检查文件是否已经缓存过了,如果缓存过了,就将数据从缓冲区(直接内存)拷贝到用户应用进程(内核态切换到用户态), 如果是第一次访问这个文件,则系统先将数据先拷贝到缓冲区(直接内存),然后CPU将数据从缓冲区拷贝到应用进程内(内核态切换到用户态), 应用进程收到内核的数据后发起write调用,将数据拷贝到目标文件相关的堆栈内存(用户态切换到内核态), 最后再从缓存拷贝到目标文件。

根据上面普通拷贝的过程我们知道了其缺点主要有:

  1. 用户态与内核态之间的上下文切换次数较多(用户态发送系统调用与内核态将数据拷贝到用户空间)。
  2. 拷贝次数较多,每次IO都需要DMA和CPU拷贝。

而零拷贝正是针对普通拷贝的缺点做了很大改进,使得其拷贝速度在处理大数据的时候很是出色。

Zero Copy方式:

从上图中可以清楚的看到,Zero Copy的模式中,避免了数据在用户空间和内存空间之间的拷贝,从而提高了系统的整体性能。Linux中的sendfile()以及Java NIO中的FileChannel.transferTo()方法都实现了零拷贝的功能,而在Netty中也通过在FileRegion中包装了NIO的FileChannel.transferTo()方法实现了零拷贝。

零拷贝主要有两种实现技术:

  1. 内存映射(mmp)
  2. 文件传输(sendfile)

可以参照我编写的demo进行接下来的学习:

zerocopy

内存映射(Memory Mapped)

内存映射对应JAVA NIO的API为
FileChannel.map。

当用户程序发起 mmp 系统调用后,操作系统会将文件的数据直接映射到内核缓冲区中, 且缓冲区会与用户空间共享这一块内存,这样就无需将数据从内核拷贝到用户空间了,用户程序接着发起write 调用,操作系统直接将内核缓冲区的数据拷贝到目标文件的缓冲区,最后再将数据从缓冲区拷贝到目标文件。

其过程如下:

内存映射由原来的四次拷贝减少到了三次,且拷贝过程都在内核空间,这在很大程度上提高了IO效率。

但是mmp也有缺点: 当我们使用mmp映射一个文件到内存并将数据write到指定的目标文件时, 如果另一个进程同时对这个映射的文件做出写的操作,用户程序可能会因为访问非法地址而产生一个错误的信号从而终止。

试想一种情况:我们的服务器接收一个客户端的下载请求,客户端请求的是一个超大的文件,服务端开启一个线程 使用mmp和write将文件拷贝到Socket进行响应,如果此时又有一个客户端请求对这个文件做出修改, 由于这个文件先前已经被第一个线程mmp了,可能第一个线程会因此出现异常,客户端也会请求失败。

解决这个问题的最简单的一种方法就对这个文件加读写锁,当一个线程对这个文件进行读或写时,其他线程不能操作此文件, 不过这样处理并发的能力可能就大打折扣了。

文件传输(SendFile)

文件传输对应JAVA NIO的API为
FileChannel.transferFrom/transferTo

在了解sendfile之前,先来看一下它的函数原型(linux系统的同学可以使用 man sendfile 查看):

#include<sys/sendfile.h>ssize_t sendfile(int out_fd,int in_fd,off_t *offset,size_t count);

sendfile在代表输入文件的文件描述符 in_fd 和 输入文件的文件描述符 out_fd 之间传输文件内容, 这个传输过程完全是在内核之中进行的,程序只需要把输入文件的描述符和输出文件的描述符传递给 sendfile调用,系统自然会完成拷贝。 当然,sendfile和mmp一样都有相同的缺点,在传输过程中, 如果有其他进程截断了这个文件的话,用户程序仍然会被终止。

sendfile传输过程如下:

它的拷贝次数与mmp一样,但是无需像mmp一样与用户进程共享内存了。

【Netty】传输(Transport)相关推荐

  1. Netty - 传输

    2019独角兽企业重金招聘Python工程师标准>>> Channel Netty 传输API的核心是:interface Channel,被用于所有的I/O操作.类层次结构: In ...

  2. netty案例,netty4.1中级拓展篇四《Netty传输文件、分片发送、断点续传》

    前言介绍 1.在实际应用中我们经常使用到网盘服务,他们可以高效的上传下载较大文件.那么这些高性能文件传输服务,都需要实现的分片发送.断点续传功能. 2.在Java文件操作中有RandomAccessF ...

  3. netty传输html页面,java 文件传输(netty) 实例源码

    服务器端: package com.rrkd.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Ch ...

  4. netty 文件传输服务器,Netty之二进制文件传输

    传输会话简要 客户端发起一个文本请求给服务器端, 服务器端解析里面文本, 返回文件给客户端, 客户端解析文件 服务器端 因为示例文件比较小, 所以没有做分段传输, 而是直接一次性把整个文件byte[] ...

  5. java nio oio_Netty NIO transport OIO transport

    Netty NIO transport && OIO transport OIO  transport The  OIO  transport  is  a  compromise(妥 ...

  6. (7)Artemis传输配置

    1.接收器(Acceptor) 在Artemis传输中接收器是一个重要的概念,如下broker.xml中接收器的配置: <acceptor name="netty">t ...

  7. 简易 IM 双向通信电脑端 GUI 应用——基于 Netty、JavaFX、多线程技术等

    简易 IM 双向通信电脑端 GUI 应用--基于 Netty.JavaFX.多线程技术等 说明 运行效果 核心代码 完整代码 参考知识 说明   这是一个使用 Netty 来实现 IM 双向通信的 d ...

  8. 如何用Netty写一个高性能的分布式服务框架?

    byte[] -->堆外内存 / 堆外内存--> byte[] -->java对象. 优化:省去 byte[] 环节,直接 读/写 堆外内存,这需要扩展对应的序列化框架. Strin ...

  9. Netty4.x 的逆袭之路 —— 再识 Netty

    Netty4.x 的逆袭之路 2020年9月25日 Netty 结合 protobuf 使用 预习 在netty数据传输过程中可以有很多选择,比如:字符串.json.xml.java对象,但为了保证传 ...

最新文章

  1. 机器人瓦力船长机器人_警察“瓦力”来啦!机器人巡逻南京路 这样的它你喜欢吗?...
  2. Tengine编译安装config项目清单
  3. 关于datagrid中控件利用js调用后台方法事件的问题
  4. app制作流程步骤_企业画册设计流程总结 告诉你画册制作步骤
  5. (仿头条APP项目)4.父类BaseFragment创建,用retrofit和gson获取并解析服务器端数据
  6. Log4Net 最简配置
  7. 把一个人的特点写具体作文_把一个人的特点写具体作文
  8. 前端学习(2833):样式rpx
  9. 三大运营商一季度财报出炉:营收集体下降
  10. idea tomcat配置
  11. 可视化数据展示工具ChatSQL
  12. 去除非ascii字符以及ascii中的控制符
  13. mysql去掉乱码_mysql消除乱码方法集
  14. JS获取本机IP地址的方法
  15. win7将html设为桌面背景,win7系统将桌面背景设置为自己心仪类型的方法
  16. TeamTalk HttpClient详解
  17. Error parsing INI config file: the argument ('true??') for option 'logappend' is invalid.
  18. [面试][PTA]充满趣味的程序员文史综合卷
  19. 联想服务器linux系统raid驱动,ThinkSystem服务器RAID 530/930系列阵列卡驱动及安装RHEL7.3要点说明...
  20. 模拟电子电路基础——放大器理解与梳理

热门文章

  1. Nature子刊:改进宏基因组的分箱和组装的新方法
  2. QIIME 2教程. 19使用q2-vsearch聚类ASVs为OTUs(2020.11)
  3. ISME:Micrarchaeota和Parvarchaeota古菌门的代谢多样性
  4. 自动刷新某个指定网页
  5. 公共基因表达数据分析系统genevestigator,再也不愁表达数据的查询和比较了
  6. Error: ‘\R‘ is an unrecognized escape in character string starting “‘E:\R“
  7. R语言使用aov函数进行双因素方差分析(Two-way factorial ANOVA)、使用HH包中的interaction2wt函数为任何阶的双因素方差分析可视化主效应和交互作用图、箱图显示主效应
  8. 贝叶斯岭回归(BayesianRidge)、自动关联决策回归、高斯过程、核函数、及高斯回归、高斯过程分类
  9. 顺序特征选择器(SequentialFeatureSelector (SFS))
  10. linux的iso镜像机没有redis,在Linux系统上安装Redis【避坑篇】