标签:操作系统特性 bio 怎么 tps 纵向扩展 soc 编程 unp 思考
输入输出是操作系统不可或缺的一部分,大致分为两类:面向磁盘和面向网络。在 Java 中有3种 I/O 类型:BIO、NIO 和 AIO,分别是同步阻塞、同步非阻塞和异步非阻塞 I/O,这里着重描述 BIO 和 NIO 的区别和常用的编程模型。
一个直接原因就是为了更好的利用操作系统特性,改善和扩展原有 API。与 NIO 相关的规范有两个:
那么,传统的 BIO 又有什么弊端?NIO 又是如何改进的?可以从两方面进行说明。
关于 java.io.file,它的不足之处在于:
而 NIO 支持批量获取文件属性,对文件、目录的处理也重新设计,提供 FileLock、MappedByteBuffer 等支持 OS 高级功能。
BIO 是同步阻塞、基于流的 I/O,阻塞就意味着当 Socket 输入流中无数据可读取时,调用线程挂起,直到有数据读取,期间不能处理其他请求,如果来了一个新连接,就只能再新建一个线程处理。
随着连接数的增加,BIO 将会创建大量线程,而一个计算机能打开的进程数或线程数是有限的,严重的时候可能会导致应用崩溃无响应。一个有效的解决办法是使用线程池,限制最大线程数,但它同时也限制了最大连接数。
NIO 将读写改为非阻塞,无数据可读,线程返回线程池,可用于处理其他连接。它对原始 I/O 提供了新的抽象 - Channel(通道),并且提供基于缓冲区的读写 API。Channel 表示一个到硬件设备、文件或网络套接字的连接,与 java.net.Socket 的区别是:
相同环境下,BIO 的线程全程只处理一条连接,而 NIO 的线程可处理多个连接,提高了系统的吞吐能力。NIO 在服务器进行纵向扩展(比如增加内存、CPU)或者横向扩展(比如增加服务器)往往能够比 BIO 带来更高的处理能力,使服务器具有更强的可扩展性和可伸缩性。
NIO 还有一个零拷贝的概念,零拷贝是指 CPU 不执行将数据从一个存储区复制到另一个存储区的操作。OS 级别的零拷贝指的是将数据发送到硬件驱动程序(网卡或磁盘驱动器)时避免从一个位置复制到另一个位置(一般是从用户空间到内核空间),反之亦然。NIO 中的零拷贝就是这样,只不过它只针对在网络上发送文件。
一般的,我们潜意识的会认为 NIO 比 BIO 的性能高,其实不尽然,当然了有个读取方式的问题,read(byte[]) 和 read(ByteBuffer)应该没区别吧?所以如果系统的并发量不高,两个用谁都行。
BIO 的问题通常会在海量的连接下体现出来,由于它不能充分利用、压榨一台服务器的性能,不管怎么扩展,它能处理的连接数与机器性能往往是非线性的,付出和收获不成正比。如果你的应用面临的连接不断增加,特别是存在大量的长连接,此时就要选择 NIO,它不仅提高了单机处理能力,还能节省服务器成本。
NIO 相比 BIO 的重点在于可扩展性,在选择 I/O 模型时,需要结合业务场景,综合考虑以下几点:
BIO 的编程模型是一连接一处理线程,采用线程池优化。
NIO 典型的编程模型是 Reactor,事件复用器通知套接字何时准备好读取和写入操作的事件,将事件传递给合适的处理程序,由该程序负责实际的读取或写入。对于读操作基本过程如下:
与 Reactor 相对的还有一个 AIO 的 Proactor 模型,它是异步 I/O,事件复用器等待 I/O 操作完成的事件,它是真正的异步,因为实际的 I/O 操作完全由操作系统执行。对于读操作,它的做法是:
I/O 模型经常对比的是阻塞和非阻塞,还有同步和异步,在《UNIX 网络编程》第6章已经给出了它们的区别,并且给出的图示很直观。这里简单做下说明,以 UDP 为例,读取一个数据包可以分为两个阶段:
阻塞和非阻塞描述的是第一阶段无数据可读取时线程是否挂起;同步和异步描述的是第二阶段,在数据复制过程中线程是否参与和挂起。注意 NIO/BIO 都是同步 I/O,NIO 对应 UNP 中描述的 I/O 复用模型。
标签:操作系统特性 bio 怎么 tps 纵向扩展 soc 编程 unp 思考
原文地址:https://www.cnblogs.com/wskwbog/p/10539782.html