I/O通信模型(BIO,NIO,AIO)
一、傳統的BIO
網絡編程的基本模型是Client/Server模型,也就是兩個進程之間進行相互通信,其中服務端提供位置信息(綁定的IP地址和監聽端口),客戶端通過連接操作向服務端監聽的地址發起連接請求,通過三次握手建立連接,如果連接建立成功,雙方就可以通過網絡套接字(Socket)進行通信。
在基于傳統同步阻塞模型開發中,ServerSocket負責綁定IP地址,啟動監聽端口,Socket負責發起連接操作,連接成功之后,雙方通過輸入和輸出流進行同步阻塞式通信。
1.1、BIO通信模型圖
首先,我們通過下面的通信模型圖來熟悉下BIO的服務端通信模型:采用BIO通信模型的服務端,通常由一個獨立的Acceptor線程負責監聽客戶端的連接,它接收到客戶端連接請求之后為每個客戶端創建一個新的線程進行鏈路處理,處理完成之后,通過輸出流返回應答給客戶端,線程銷毀。這就是典型的一請求一應答通信模型。
該模型最大的問題就是缺乏彈性伸縮能力,當客戶端并發訪問量增加后,服務端的線程個數和客戶端并發訪問數呈1:1的正比關系,由于線程是JAVA虛擬機非常寶貴的系統資源,當線程數膨脹之后,系統的性能將急劇下降,隨著并發訪問量的繼續增大,系統會發生線程堆棧溢出、創建新線程失敗等問題,并最終導致進程宕機或者僵死,不能對外提供服務。
它的弊端有很多:
1.性能問題:一連接一線程模型導致服務端的并發接入數和系統吞吐量受到極大限制;
2.可靠性問題:由于I/O操作采用同步阻塞模式,當網絡擁塞或者通信對端處理緩慢會導致I/O線程被掛住,阻塞時間無法預測;
3.可維護性問題:I/O線程數無法有效控制、資源無法有效共享(多線程并發問題),系統可維護性差;
二、偽異步IO編程
為了解決同步阻塞IO面臨的一個鏈路需要一個線程處理的問題,后來有人對它的線程模型進行了優化,后端通過一個線程池來處理多個客戶端的請求接入,形成客戶端個數M:線程池最大線程數N的比例關系,其中M可以遠遠大于N,通過線程池可以靈活的調配線程資源,設置線程的最大值,防止由于海量并發接入導致線程耗盡。 下面,我們結合連接模型圖和源碼,對偽異步IO進行分析,看它是否能夠解決同步阻塞IO面臨的問題。
2.1、偽異步IO模型圖
采用線程池和任務隊列可以實現一種叫做偽異步的IO通信框架,它的模型圖如下:
當有新的客戶端接入的時候,將客戶端的Socket封裝成一個Task(該任務實現java.lang.Runnable接口)投遞到后端的線程池中進行處理,JDK的線程池維護一個消息隊列和N個活躍線程對消息隊列中的任務進行處理。由于線程池可以設置消息隊列的大小和最大線程數,因此,它的資源占用是可控的,無論多少個客戶端并發訪問,都不會導致資源的耗盡和宕機。?
?三、NIO(多路復用器Selector)
幾乎所有的中文技術書籍都將Selector翻譯為選擇器,但是實際上我認為這樣的翻譯并不恰當,選擇器僅僅是字面上的意思,這樣翻譯體現不出Selector的功能和特點。
在前面的章節我們介紹過Java NIO的實現關鍵是通過多路復用IO技術實現的,多路復用的核心就是通過Selector來輪詢注冊在其上的Channel,當發現某個或者多個Channel處于就緒狀態后,從阻塞狀態返回就緒的Channel的選擇鍵集合,進行IO操作。由于多路復用器是NIO實現非阻塞IO的關鍵,它又是主要通過Selector實現,所以本書將Selector翻譯為多路復用器,它與其它技術書籍所說的選擇器是同一個東西,請大家了解。
?四、AIO異步IO
總結
以上是生活随笔為你收集整理的I/O通信模型(BIO,NIO,AIO)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java多线程(3) Volatile的
- 下一篇: 数据分析系列剧第四集:行业研究报告与生产