本文引用 : https://blog.csdn.net/yinwenjie/article/details/48472237

目前常用的IO通信模型包括四种:阻塞式同步IO、非阻塞式同步IO、多路复用IO和真正的异步IO。所有IO模式都是要靠操作系统进行支持,应用程序只是提供相应的实现,对操作系统进行调用。

1. 传统阻塞模式(BIO)

BIO就是:blocking IO。最容易理解、最容易实现的IO工作方式,**应用程序向操作系统请求网络IO操作,这时应用程序会一直等待;另一方面,操作系统收到请求后,也会等待,直到网络上有数据传到监听端口;操作系统在收集数据后,会把数据发送给应用程序;最后应用程序受到数据,并解除等待状态。**如下图所示:

注意:上图中交互的两个元素是应用程序和它所使用的操作系统
就TCP协议来说,整个过程实际上分成三个步骤:三次握手建立连接、传输数据(包括验证和重发)、断开连接。

BIO存在的问题:

  • 同一时间,服务器只能接受来自于客户端A的请求信息;虽然客户端A和客户端B的请求是同时进行的,但客户端B发送的请求信息只能等到服务器接受完A的请求数据后,才能被接受。
  • 由于服务器一次只能处理一个客户端请求,当处理完成并返回后(或者异常时),才能进行第二次请求的处理。很显然,这样的处理方式在高并发的情况下,是不能采用的。
  • 实际上以上的问题是可以通过多线程来解决的,实际上就是当accept接收到一个客户端的连接后,服务器端启动一个新的线程,来读写客户端的数据,并完成相应的业务处理。但是你无法影响操作系统底层的“同步IO”机制。

2. 非阻塞模式(NIO)

一定要注意:阻塞/非阻塞的描述是针对应用程序中的线程进行的,对于阻塞方式的一种改进是应用程序将其“一直等待”的状态主动打开,如下图所示:

这种模式下,应用程序的线程不再一直等待操作系统的IO状态,而是在等待一段时间后,就解除阻塞。
引入了多线程技术后,IO的处理吞吐量大大提高了,但是这样做就真的没有问题了吗,您要知道操作系统可是有“最大线程”限制的:

  • 虽然在服务器端,请求的处理交给了一个独立线程进行,但是操作系统通知accept()的方式还是单个处理的(甚至都不是非阻塞模式)。也就是说,实际上是服务器接收到数据报文后的“业务处理过程”可以多线程(包括可以是非阻塞模式),但是数据报文的接受还是需要一个一个的来。
  • 在linux系统中,可以创建的线程是有限的。我们可以通过cat /proc/sys/kernel/threads-max 命令查看可以创建的最大线程数。当然这个值是可以更改的,但是线程越多,CPU切换所需的时间也就越长,用来处理真正业务的需求也就越少
  • 创建一个线程是有较大的资源消耗的。JVM创建一个线程的时候,即使这个线程不做任何的工作,JVM都会分配一个堆栈空间。这个空间的大小默认为128K,您可以通过-Xss参数进行调整。
  • 可以使用ThreadPoolExecutor线程池来缓解线程的创建问题,但是又会造成BlockingQueue积压任务的持续增加同样消耗了大量资源。另外,如果您的应用程序大量使用长连接的话,线程是不会关闭的。这样系统资源的消耗更容易失控。

最后,无论您是使用的多线程、还是加入了非阻塞模式,这都是在应用程序层面的处理,而底层socketServer所匹配的操作系统的IO模型始终是“同步IO”,最根本的问题并没有解决。

那么,如果你真想单纯使用线程来解决问题,那么您自己都可以计算出来您一个服务器节点可以一次接受多大的并发了。看来,单纯使用线程解决这个问题不是最好的办法。

3. 多路复用IO(IO Multiplex)

目前流程的多路复用IO实现主要包括四种:select、poll、epoll、kqueue。下表是他们的一些重要特性的比较:

多路复用IO技术最适用的是“高并发”场景,所谓高并发是指1毫秒内至少同时有上千个连接请求准备好 QPS~100W。其他情况下多路复用IO技术发挥不出来它的优势。

3.1 重要概念:Channel

通道,被建立的一个应用程序和操作系统交互事件、传递内容的渠道(注意是连接到操作系统)。一个通道会有一个专属的文件状态描述符。那么既然是和操作系统进行内容的传递,那么说明应用程序可以通过通道读取数据,也可以通过通道向操作系统写数据。

3.2 重要概念:Buffer

数据缓存区:在JAVA NIO 框架中,为了保证每个通道的数据读写速度JAVA NIO 框架为每一种需要支持数据读写的通道集成了Buffer的支持。

这句话怎么理解呢?例如ServerSocketChannel通道它只支持对OP_ACCEPT事件的监听,所以它是不能直接进行网络数据内容的读写的。所以ServerSocketChannel是没有集成Buffer的。

Buffer有两种工作模式:写模式和读模式。在读模式下,应用程序只能从Buffer中读取数据,不能进行写操作。但是在写模式下,应用程序是可以进行读操作的,这就表示可能会出现脏读的情况。所以一旦您决定要从Buffer中读取数据,一定要将Buffer的状态改为读模式。

3.3 重要概念:Selector

Selector的英文含义是“选择器”,不过根据我们详细介绍的Selector的岗位职责,您可以把它称之为“轮询代理器”、“事件订阅器”、“channel容器管理机”都行。

  • 事件订阅和Channel管理:
    应用程序将向Selector对象注册需要它关注的Channel,以及具体的某一个Channel会对哪些IO事件感兴趣。Selector中也会维护一个“已经注册的Channel”的容器。
  • 轮询代理:
    应用层不再通过阻塞模式或者非阻塞模式直接询问操作系统“事件有没有发生”,而是由Selector代其询问。
  • 实现不同操作系统的支持:
    之前已经提到过,多路复用IO技术 是需要操作系统进行支持的,其特点就是操作系统可以同时扫描同一个端口上不同网络连接的时间。所以作为上层的JVM,必须要为不同操作系统的多路复用IO实现编写不同的代码。

通过上文的描述,我们知道了多路复用IO技术是操作系统的内核实现。在不同的操作系统,甚至同一系列操作系统的版本中所实现的多路复用IO技术都是不一样的。那么作为跨平台的JAVA JVM来说如何适应多种多样的多路复用IO技术实现呢?面向对象的威力就显现出来了:无论使用哪种实现方式,他们都会有“选择器”、“通道”、“缓存”这几个操作要素,那么可以为不同的多路复用IO技术创建一个统一的抽象组,并且为不同的操作系统进行具体的实现。JAVA NIO中对各种多路复用IO的支持,主要的基础是java.nio.channels.spi.SelectorProvider抽象类,其中的几个主要抽象方法包括:

  • public abstract DatagramChannel openDatagramChannel():创建和这个操作系统匹配的UDP 通道实现。

  • public abstract AbstractSelector openSelector():创建和这个操作系统匹配的NIO选择器,就像上文所述,不同的操作系统,不同的版本所默认支持的NIO模型是不一样的。

  • public abstract ServerSocketChannel openServerSocketChannel():创建和这个NIO模型匹配的服务器端通道。

  • public abstract SocketChannel openSocketChannel():创建和这个NIO模型匹配的TCP Socket套接字通道(用来反映客户端的TCP连接)

多路复用IO的优缺点:

  • 不用再使用多线程来进行IO处理了(包括操作系统内核IO管理模块和应用程序进程而言)。当然实际业务的处理中,应用程序进程还是可以引入线程池技术的
  • 同一个端口可以处理多种协议,例如,使用ServerSocketChannel测测的服务器端口监听,既可以处理TCP协议又可以处理UDP协议。
  • 操作系统级别的优化:多路复用IO技术可以是操作系统级别在一个端口上能够同时接受多个客户端的IO事件。同时具有之前我们讲到的阻塞式同步IO和非阻塞式同步IO的所有特点。Selector的一部分作用更相当于“轮询代理器”。
  • 都是同步IO:目前我们介绍的 阻塞式IO、非阻塞式IO甚至包括多路复用IO,这些都是基于操作系统级别对“同步IO”的实现。

我们一直在说“同步IO”,一直都没有详细说,什么叫做“同步IO”。实际上一句话就可以说清楚:只有上层(包括上层的某种代理机制)系统询问我是否有某个事件发生了,否则我不会主动告诉上层系统事件发生了。很明显,这里是可以继续优化的。

4. 异步IO(真正的NIO,AIO)

上述阻塞式同步IO、非阻塞式同步IO、多路复用IO 说明了IO模型是由操作系统提供支持,且这三种IO模型都是同步IO,都是采用的“应用程序不询问我,我绝不会主动通知”的方式。
异步IO则是采用“订阅-通知”模式:即应用程序向操作系统注册IO监听,然后继续做自己的事情。当操作系统发生IO事件,并且准备好数据后,在主动通知应用程序,触发相应的函数

和同步IO一样,异步IO也是由操作系统进行支持的。微软的windows系统提供了一种异步IO技术:IOCP(I/O Completion Port,I/O完成端口);Linux下由于没有这种异步IO技术,可以使用的是epoll对异步IO进行模拟。

系统间通信4:基本IO通信模型相关推荐

  1. 架构设计:系统间通信(4)——IO通信模型和JAVA实践 中篇

    接上篇<架构设计:系统间通信(3)--IO通信模型和JAVA实践 上篇> 4.多路复用IO模型 在"上篇"文章中,我们已经提到了使用多线程解决高并发场景的问题所在,这篇 ...

  2. 架构设计:系统间通信(5)——IO通信模型和JAVA实践 下篇

    接上篇:<架构设计:系统间通信(4)--IO通信模型和JAVA实践 中篇>,我们继续讲解 异步IO 7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用I ...

  3. 系统间通信2:通信管理与远程方法调用RMI

    本文引用 : https://yinwj.blog.csdn.net/article/details/49120813 RMI : Remote Method Invocation,远程方法调用 RP ...

  4. 系统间通信1:阻塞与非阻塞式通信B

    版权声明:本文引用https://yinwj.blog.csdn.net/article/details/48274255 接上篇:系统间通信1:阻塞与非阻塞式通信A 4.3 NIO通信框架 目前流行 ...

  5. 系统间通信1:阻塞与非阻塞式通信A

    版权声明:本文引用https://yinwj.blog.csdn.net/article/details/48274255 从这篇博文开始,我们将进入一个新文章系列.这个文章系列专门整理总结了目前系统 ...

  6. 架构设计:系统间通信(36)——Apache Camel快速入门(上)

    1.本专题主旨 1-1.关于技术组件 在这个专题中,我们介绍了相当数量技术组件:Flume.Kafka.ActiveMQ.Rabbitmq.Zookeeper.Thrift .Netty.DUBBO等 ...

  7. 架构设计:系统间通信(10)——RPC的基本概念

    1.概述 经过了详细的信息格式.网络IO模型的讲解,并且通过JAVA RMI的讲解进行了预热.从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的讲解:RPC.在后续的几篇文章中,我们首先讲解R ...

  8. 架构设计:系统间通信(31)——其他消息中间件及场景应用(下1)

    接上文:<架构设计:系统间通信(30)--Kafka及场景应用(中3)> 5.场景应用--电商平台:浏览记录收集功能 事件/日志收集系统是大中型软件不得不面对的话题.目前第三方业务系统对 ...

  9. 架构设计:系统间通信(1)——概述从“聊天”开始上篇

    从这篇博文开始,我们将进入一个新文章系列.这个文章系列专门整理总结了目前系统间通信的主要原理.手段和实现.我们将讲解典型的信息格式.讲解传统的RMI调用并延伸出来重点讲解RPC调用和使用案例:最后我们 ...

  10. Dubbo系统间通信

    系统间通信 远程通信,实现方案 Webservice Restful Dubbo Webservice 基于soap协议,通信效率不高 主要特点,跨语言.跨平台 项目中,不推荐使用 可用于,不同公司之 ...

最新文章

  1. Linux中的动态库和静态库(.a/.la/.so/.o)
  2. mysql 5.0 修改字符集_修改及查看mysql数据库的字符集
  3. php在html里面的位置,关于script在html中的摆放位置解析
  4. python中把输出结果写到一个文件中_Python3.6笔记之将程序运行结果输出到文件的方法...
  5. 如何从io.Reader 中读数据
  6. 一些js/css动画 mark
  7. 【软件工程】第一次阅读作业
  8. easy Connect连接成功,但是虚拟IP地址获取失败,而导致网页无法打开
  9. jvm 调优 2020.09.07
  10. myline java线段类,2008010 编写一个线段类 MyLine 联合开发网 - pudn.com
  11. iPhone上塔罗牌测试软件,塔罗牌占卜:测Ta对你是用情至深还是一时兴起?准到没朋友!...
  12. java 无法加载dll_java中调用本地动态链接库(*.DLL)的两种方式详解和not found library、打包成jar,war包dll无法加载等等问题解决办法...
  13. Moya、RxMoya基本使用
  14. 《C++程序设计上机实践及学习辅导》实验报告
  15. j2cache两级缓存框架
  16. ClickHouse-尚硅谷(1. 入门-概述)学习笔记
  17. @Autowired的原理简识
  18. iso体系认证有哪些?
  19. 企业容器云管理平台选型指南
  20. 斐讯N1保姆级教程 电视盒 debian centos7 三合一

热门文章

  1. #11 压缩与解压缩
  2. The server time zone value
  3. 【转载】解决Windows和Ubuntu时间不一致的问题
  4. iOS 各种编译错误汇总
  5. 屌丝程序员的返京历险记
  6. 老鼠的求爱之旅 (DP)
  7. hdu 5086(dp)
  8. activiti 图片
  9. 阮一峰网络日志 第41期 2019年01月25日
  10. 转: 基于elk 实现nginx日志收集与数据分析