BIO 通信
一线程对一客户端
伪异步IO 通信
nio通信
aio 通信
四种io 对比
NIO 通信
Java IO 通信
bio通信的特点
BIO 同步阻塞IO
伪异步IO通信(线程池处理)
NIO 同步非堵塞IO
AIO 异步非堵塞IO
1111111
1:BIO 服务端一个线程会负责一个连接,进行请求的处理和响应,比较明显,当客户端比较多的时候,服务端的线程可能就不够了,这时候对应的请求就没法及时处理了
客户端个数:服务端处理线程个数=1:1
IO类型:阻塞同步
API使用难度:简单
调试难度:简单
NIO 所有的数据都是通过缓冲区处理的,通道Channel 。Selector 轮询Channel
BIO通信:一个线程负责连接,一请求一应答,缺乏弹性伸缩能力
客户端的个数和服务端创建的线程数呈1:1的正比关系
伪异步IO通信:线程池负责连接,M请求N应答,线程池阻塞
NIO通信:缓冲区Buffer,通道Channel,多路复用器Selector
通道Channel是双向的,可用于读、写或同时进行;流Stream只能在一个方向移动
AIO通信:连接注册读写事件和回调函数,读写方法异步,主动通知程序
提供两种方式获取操作结果:java.util.concurrent.Futrue类来表示异步操作都结果;执行异步操作时传入java.nio.channels.CompletionHandler接口都实现类作为操作完成回调
四种IO对比:(IO类型,客户端个数,API使用难度,调试难度,可靠性,吞吐量)
BIO: 阻塞同步的IO,客户端的个数与服务端的IO线程数呈1比1的关系,API使用简单,调试比较简单,可靠性非常差,吞吐量非常低
伪异步IO: 阻塞同步的IO,客户端的个数与服务端的IO线程数呈M比N的关系,API使用简单,调试简单,相比于BIO的可靠性,来说相对好一点,但也很差,吞吐量中等
NIO: 非阻塞同步的IO,客户端的个数与服务端的IO线程数呈M比1的关系, API使用复杂,调试相对复杂,可靠性要高一些,吞吐量高
AIO: 非阻塞异步IO,客户端的个数与服务端的IO线程数呈M比0的关系,不需要启动额外的IO线程,它是被动回调的,API使用复杂,调试相对复杂,可靠性比较高,吞吐量比较高
AIO通信:它是连接注册读写事件和回调函数,读写方法异步,同时它是主动通知程序。AIO异步通信提供了两种方式获取操作结果:第一种方式是通过java.util.concurrent的Future类来表示异步操作的结果;第二种方式是在执行异步操作的时候传入一个java.nio.channels.CompletionHandler接口的实现类作为操作完成回调。NIO的异步套接字回调,是真正的异步非阻塞IO,对应于Unix网络编程中的事件驱动IO,不需要通过多路复用器对被注册的通道进行轮询操作即可实现异步读写,从而简化NIO的编程模型。
NIO通信:
缓存区Buffer: 它是一个对象,它包含一些要写入或要读出的数据,在NIO中加入Buffer对象,体现了新库与原IO的重要区别。在面向流的IO中,可以将数据直接写入或者将数据直接读到Strem对象中。在NIO中,所有数据都是用缓冲区进行处理的,在读取数据时,直接读缓冲区中,在写入数据时,是直接写入缓冲区中。任何时候处理NIO中的数据时都是通过缓冲区进行操作。
通道Channel: 网络数据通过通道Channel读取和写入,通道与流的不同之处在于通道是双向的,而流只是在一个方向上移动,一个流必须是InputStream或OutputStream的子类,而通道可以用于读写或二者同时进行。
多路复用器selector: selector提供了选择已经就绪的任务的能力,会通过不断轮询在其上的Channel,在某个Channel上面发生读或者写事件,则该Channel处于就绪状态,会被Selector轮询出来,然后获取Channel的集合进行后续IO的操作。
NIO通信并没有最大连接数的限制,可以接入成千上万的客户端
伪异步IO通信模型:
当有N个新的客户端接入的时候,伪异步IO通信将客户端的socket封装成一个Task投递到后端的线程池中进行处理,JDK的线程池负责维护一个消息队列和N个活跃的线程,它与BIO通信模型最大的不同点是:伪异步IO通信的服务端不再针对每一个客户端都创建一个独立的线程,它是由一个线程池来统一处理所有客户端的接入请求。
当有大量客户端接入的时候,并发量不断上涨,将会出现线程池阻塞问题。
伪异步IO通信:当有新的客户端接入的时候,将客户端的socket封装成一个task投递到后端的线程池进行处理,线程池维护一个消息队列和N个活跃的线程,对消息队列中的任务进行相关的处理。也就是说当有M个客户端接入的时候,服务端将会创建一个具有N个线程的线程池来对客户端的请求进行处理。由于线程池可以设置消息队列的大小和最大线程数,因此它的资源占用是可控的,无论多少个客户端对它访问,都不会导致资源的耗尽和宕机。缺点:当有大量的客户端进入的时候,随着并发访问量的不断增加,伪异步IO通信可能会造成线程池阻塞。
BIO通信模型图
BIO通信:采用BIO模型通信的服务端,通常由一个独立的线程负责监听客户端的连接,它接收到客户端连接请求之后,会对每个客户端创建一个新的线程,进行链路处理,处理完成之后通过输出流返回应答给客户端,此时线程销毁,这就是典型的”一请求一应答“的通信模型。该模型的最大缺点就是:缺乏弹性伸缩能力,当客户端并发访问量增加以后,服务端的线程个数和客户端的并发访问数会成1比1的正比关系,由于线程是Java虚拟机的宝贵系统资源,当线程数膨胀之后,系统的性能就会快速下降。随着并发访问量的继续增大,系统将会发生线程堆栈异常或创建线程失败等问题。最终导致进程宕机或将死,不能对外提供服务。
aio通信模型
nio通信模型
伪异步io通信模型
bio通信模型
bio相关概念
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。
BIO通信:服务端接收到客户端的请求之后,为每一个客户端创建一个线程进行处理,通过输出流把应答发送给客户端,最后销毁线程。(1对1,阻塞同步的IO)
伪异步IO通信:当有新的客户端接入的时候,将客户端的socket封装成一个task投递到后端的线程池进行处理,线程池维护一个消息队列和N个活跃的线程,对消息队列中的任务进行相关的处理。(M对N,阻塞同步的IO)
NIO通信:在面向流的IO中可以将数据直接写入或者将数据直接读到Stream对象中,在NIO中,所有数据都是用缓冲区进行处理的,在读取数据时,直接读缓冲区中,在写入数据时,是直接写入缓冲区中。任何时候处理NIO中的数据时都是通过缓冲区进行操作。网络数据通过Channel读取和写入。selector提供了选择已经就绪的任务的能力,会通过不断轮询在其上的Channel,在某个Channel上面发生读或者写事件,则该Channel处于就绪状态,会被Selector轮询出来,然后获取Channel的集合进行后续的操作。(M对1,非阻塞同步的IO)
AIO通信:AIO的异步套接自通道,是真正的异步非阻塞IO,对应于Unix网络编程中的事件驱动IO,不需要通过多路复用器对被注册的通道进行轮询操作即可实现异步读写,从而简化NIO的编程模型。(M对0,非阻塞异步IO)
java中的IO:BIO、伪异步IO、AIO、NIO
BIO:一个线程负责连接 、一请求一应答、缺乏弹性伸缩能力(线程数增加后系统性能极具下降);
伪异步IO:线程池负责连接、M请求N连接、线程池可以是线程资源可控(设置最大连接数等)但是会产生线程池阻塞;
NIO:缓冲区Buffer(NIO中的数据读写都是通过缓冲区buffer操作)、通道Channel(可以是双向的,流是单向的)、多路复用器Selector(轮询出就绪状态的Channel的集合,可以进行后续的IO操作,没有最大连接数限制);
AIO:连接注册读写事件和回调函数(事件驱动IO)、读写方法异步(真正的异步非阻塞IO)、主动通知程序
客户端个数:
BIO(同步阻塞IO):一比一
伪异步IO(同步阻塞IO):M比N
NIO(同步非阻塞):M比1
AIO(异步非阻塞):M比0,不需要启动额外线程,被动回调
AIO通信:
连接注册读写事件和回调函数
读写方法异步
主动通知程序
NIO通信:
缓冲区Buffer负责读/写数据
通道Channel读写同时进行
多路复用器Selector轮询一个或多个Channel是否可读、可写
NIO没有最大连接数限制,可以接入成千上万个客户端
伪异步IO通信:线程池负责连接,M请求N应答,可能造成线程池阻塞
BIO通信:一个线程负责连接,一请求一应答,缺乏弹性伸缩能力