课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
线程是我们在学习软件编程开发的时候需要掌握的重点技术知识之一,而今天我们就通过案例分析来了解一下常用的几个线程模型。
什么是I/O多路复用
学习I/O多路复用之前,我们先来了解如下几个概念:
阻塞I/O:客户端从socket中读取数据或写入数据时,如果读取时流中没有数据,写入时缓冲区已满,就需要block,知道流中有数据或者缓冲区的数据被排空。
非阻塞I/O:客户端从流中读取数据,如果流中没有数据,则立即返回,不发生block。
同步I/O:同步I/O将导致请求的I/O操作一直被block,直到I/O完成。
异步I/O:异步I/O不会导致block,发出I/O请求后立即返回,直到完成I/O操作后再异步通知调用进程。
I/O多路复用可以监视多个FD(文件描述符),一旦某个FD准备就绪,就会通知相应进程处理。多路复用也是阻塞的,阻塞的方法是select/poll/epoll,可以在单个进程中同时处理多个I/O请求,原理是采用轮询的方式便利所有的I/O操作,当某些I/O有数据时,就通知用户进程处理。
select:系统提供select函数来实现多路复用输入/输出模型,select系统调用是用来让我们的程序监视多个文件句柄的状态变化。程序会阻塞在select函数上,直到被监视的文件句柄中有一个或多个发生了状态变化。
poll:poll函数与select函数的大不同之处在于:select函数有大文件描述符的限制,一般1024个,而poll函数对文件描述符的数量没有限制。
epoll:
监视的描述符数量不受限制,所支持的FD上限是Linux系统大可以打开文件的数目;
I/O效率不会随着监视fd的数量增长而下降。epoll不同于select和poll轮询的方式,而是通过每个fd定义的回调函数来实现的,只有就绪的fd才会执行回调函数。
Reactor三种线程模型
1.Reactor单线程模型
是指所有的I/O操作都在同一个NIO线程上完成,职责如下
作为NIO服务端,接收客户端TCP连接
作为NIO客户端,向服务端发起TCP连接
读取对端请求或者应答消息
向对端发送请求或者应答消息
在一些小容量场景下,可以使用多线程模型,但对于高负载场景下并不适用,原因如下:
一个NIO线程同时处理成百上千的连接,性能上无法保证。
NIO线程负载过重,处理速度会越来越慢,会导致大量客户端连接超时
一旦NIO线程跑飞,或者死循环,会导致整个系统的不可用
2.Reactor多线程模型
与单线程模型大的区别是,有一组NIO来处理I/O请求,特点如下
有一个NIO线程——Acceptor线程用户监听客户端的连接
有一个NIO线程池负责I/O的读写操作,该线程池可以是基于JDK的线程池。
3.主从Reactor多线程模型
如果并发百万的客户端连接,在Reactor多线程模型下只有一个NIO的Acceptor线程处理客户端连接会有性能问题。主从Reactor线程模型的特点是:服务端用于接收客户端的连接不再是一个单独的NIO线程,而是一个NIO的Acceptor线程池。Acceptor接收到客户端的TCP连接请求处理完成后,将新创建的ChannelSocket注册到I/O线程池(subreactor线程池)上的某一个线程上,由I/O负责后续的I/O读写操作。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。