网络编程中,哪种IO模型适用于处理请求?
摘要:我们讨论网络编程中的IO模型时,需要先明确什么是IO以及IO操作为什么在程序开发中是很关键的一部分,首先我们看下IO的定义。 IO的定义 IO操作(InputOutput操作)是计算机系统中的一种重要操作,用于数据的输入和输出,通常涉及到
我们讨论网络编程中的IO模型时,需要先明确什么是IO以及IO操作为什么在程序开发中是很关键的一部分,首先我们看下IO的定义。
IO的定义
IO操作(Input/Output操作)是计算机系统中的一种重要操作,用于数据的输入和输出,通常涉及到计算机与外部设备(如硬盘、网卡、键盘、鼠标、打印机等)之间的数据传输和交互的都可以认为是IO操作。
IO操作可以分为两种主要类型:
1 输入操作(Input)指从外部设备或数据源中读取数据到计算机内存或程序当中。例如从硬盘读取文件内容、从键盘接收用户的输入、从网卡接收数据等.
2 输出操作(Output)指将计算机内存中的数据写入到外部设备或数据目标中。例如将数据写入到硬盘上的文件、文字打印输出、将数据发送到网络上等都属于输出操作。
无论是哪种I/O 操作分为两个部分:
数据准备,将数据加载到内核缓存。(数据加载到操作系统)
将内核缓存中的数据加载到用户缓存(从操作系统复制到应用中)
因此开发工作当中涉及到的网络读写、数据库操作、文件操作、日志打印的,都可以归为IO操作,IO操作的性能可以受到多种因素的影响,包括硬件性能、操作系统的优化、文件系统的性能等等。而网络IO特指计算机程序与网络之间进行数据交互的过程,在编码层面我们可以简单把它定义成的Socket套接字操作,如Socket的创建和关闭,数据的发送和接收。
IO的重要性
那么为什么我们要关心IO操并对应存在多种IO模型呢, 因为IO操作的本质是要与硬件进行数据交互,这个过程是需要时间的,返回的结果也是需要等待的,从而也就造成了我们经常说的阻塞问题,你的程序是需要停在那里等待的,所以在大部分程序开发场景中,IO操作通常是最耗时的操作之一,并且最容易成为性能瓶颈的关键因素,特别是一旦你的程序开始上规模的,同样的一段程序,一旦需要处理的数量级上去,就会升级成一个复杂的问题;同理网络IO之所以重要且被人反复提及,是因为网络开发特别是服务端的开发中不可能处理的是单一链接,处理100个链接与处理100万个链接面对的性能挑战是不能同日而语的,这也是C10K问题的由来,所以一些需要处理海量链接的服务应用,比如IOT物联网服务,推送服务, 为了提高IO操作的性能,通常会使用一些阻塞、非阻塞IO、异步IO模型来优化IO对整个应用的性能影响,也就是我们经常听到的BIO、NIO、AIO等IO模型,当然这只是解决上面所说问题的方案其中的一个环节。
IO依据阻塞,非阻塞,同步,异步等特点可以划分为阻塞IO(BIO)、非阻塞IO(NIO)、多路复用IO(multiplexing IO)、异步IO(AIO)。每一种IO都有他们的使用场景和优势,其中平常我们说的NIO已经包含了IO的多路复用,以下这张图各个IO和阻塞非阻塞,同步异步之间的关系。
其中阻塞、非阻塞、多路IO复用这些需要轮询处理的都是同步IO,真正的异步IO中程序只需要等待一个完成的信号的通知,也就是我们通常说的异步回调机制。所以拉一个子线程去轮训或使用select、poll、epoll都不是异步。
网络编程IO模型
上面我们阐述了IO的定义以及重要性,现在结合Java代码的具体实现看下不同IO模型的具体实现与特点。
1、 阻塞IO模型
BIO(Blocking I/O):
BIO是最传统的阻塞I/O模型,意味着当一个线程执行I/O操作时,它会一直等待直到操作完成。
每个I/O操作都需要一个独立的线程来处理,这会导致线程数量的大幅增加,降低了系统的并发性能。
适用于一般连接数不多的应用场景。
