系统间通信4:基本IO通信模型
本文引用 : https://blog.csdn.net/yinwenjie/article/details/48472237
目前常用的IO通信模型包括四種:阻塞式同步IO、非阻塞式同步IO、多路復用IO和真正的異步IO。所有IO模式都是要靠操作系統進行支持,應用程序只是提供相應的實現,對操作系統進行調用。
1. 傳統阻塞模式(BIO)
BIO就是:blocking IO。最容易理解、最容易實現的IO工作方式,**應用程序向操作系統請求網絡IO操作,這時應用程序會一直等待;另一方面,操作系統收到請求后,也會等待,直到網絡上有數據傳到監聽端口;操作系統在收集數據后,會把數據發送給應用程序;最后應用程序受到數據,并解除等待狀態。**如下圖所示:
注意:上圖中交互的兩個元素是應用程序和它所使用的操作系統
就TCP協議來說,整個過程實際上分成三個步驟:三次握手建立連接、傳輸數據(包括驗證和重發)、斷開連接。
BIO存在的問題:
- 同一時間,服務器只能接受來自于客戶端A的請求信息;雖然客戶端A和客戶端B的請求是同時進行的,但客戶端B發送的請求信息只能等到服務器接受完A的請求數據后,才能被接受。
- 由于服務器一次只能處理一個客戶端請求,當處理完成并返回后(或者異常時),才能進行第二次請求的處理。很顯然,這樣的處理方式在高并發的情況下,是不能采用的。
- 實際上以上的問題是可以通過多線程來解決的,實際上就是當accept接收到一個客戶端的連接后,服務器端啟動一個新的線程,來讀寫客戶端的數據,并完成相應的業務處理。但是你無法影響操作系統底層的“同步IO”機制。
2. 非阻塞模式(NIO)
一定要注意:阻塞/非阻塞的描述是針對應用程序中的線程進行的,對于阻塞方式的一種改進是應用程序將其“一直等待”的狀態主動打開,如下圖所示:
這種模式下,應用程序的線程不再一直等待操作系統的IO狀態,而是在等待一段時間后,就解除阻塞。
引入了多線程技術后,IO的處理吞吐量大大提高了,但是這樣做就真的沒有問題了嗎,您要知道操作系統可是有“最大線程”限制的:
- 雖然在服務器端,請求的處理交給了一個獨立線程進行,但是操作系統通知accept()的方式還是單個處理的(甚至都不是非阻塞模式)。也就是說,實際上是服務器接收到數據報文后的“業務處理過程”可以多線程(包括可以是非阻塞模式),但是數據報文的接受還是需要一個一個的來。
- 在linux系統中,可以創建的線程是有限的。我們可以通過cat /proc/sys/kernel/threads-max 命令查看可以創建的最大線程數。當然這個值是可以更改的,但是線程越多,CPU切換所需的時間也就越長,用來處理真正業務的需求也就越少。
- 創建一個線程是有較大的資源消耗的。JVM創建一個線程的時候,即使這個線程不做任何的工作,JVM都會分配一個堆棧空間。這個空間的大小默認為128K,您可以通過-Xss參數進行調整。
- 可以使用ThreadPoolExecutor線程池來緩解線程的創建問題,但是又會造成BlockingQueue積壓任務的持續增加,同樣消耗了大量資源。另外,如果您的應用程序大量使用長連接的話,線程是不會關閉的。這樣系統資源的消耗更容易失控。
最后,無論您是使用的多線程、還是加入了非阻塞模式,這都是在應用程序層面的處理,而底層socketServer所匹配的操作系統的IO模型始終是“同步IO”,最根本的問題并沒有解決。
那么,如果你真想單純使用線程來解決問題,那么您自己都可以計算出來您一個服務器節點可以一次接受多大的并發了。看來,單純使用線程解決這個問題不是最好的辦法。
3. 多路復用IO(IO Multiplex)
目前流程的多路復用IO實現主要包括四種:select、poll、epoll、kqueue。下表是他們的一些重要特性的比較:
多路復用IO技術最適用的是“高并發”場景,所謂高并發是指1毫秒內至少同時有上千個連接請求準備好 QPS~100W。其他情況下多路復用IO技術發揮不出來它的優勢。
3.1 重要概念:Channel
通道,被建立的一個應用程序和操作系統交互事件、傳遞內容的渠道(注意是連接到操作系統)。一個通道會有一個專屬的文件狀態描述符。那么既然是和操作系統進行內容的傳遞,那么說明應用程序可以通過通道讀取數據,也可以通過通道向操作系統寫數據。
3.2 重要概念:Buffer
數據緩存區:在JAVA NIO 框架中,為了保證每個通道的數據讀寫速度JAVA NIO 框架為每一種需要支持數據讀寫的通道集成了Buffer的支持。
這句話怎么理解呢?例如ServerSocketChannel通道它只支持對OP_ACCEPT事件的監聽,所以它是不能直接進行網絡數據內容的讀寫的。所以ServerSocketChannel是沒有集成Buffer的。
Buffer有兩種工作模式:寫模式和讀模式。在讀模式下,應用程序只能從Buffer中讀取數據,不能進行寫操作。但是在寫模式下,應用程序是可以進行讀操作的,這就表示可能會出現臟讀的情況。所以一旦您決定要從Buffer中讀取數據,一定要將Buffer的狀態改為讀模式。
3.3 重要概念:Selector
Selector的英文含義是“選擇器”,不過根據我們詳細介紹的Selector的崗位職責,您可以把它稱之為“輪詢代理器”、“事件訂閱器”、“channel容器管理機”都行。
- 事件訂閱和Channel管理:
應用程序將向Selector對象注冊需要它關注的Channel,以及具體的某一個Channel會對哪些IO事件感興趣。Selector中也會維護一個“已經注冊的Channel”的容器。 - 輪詢代理:
應用層不再通過阻塞模式或者非阻塞模式直接詢問操作系統“事件有沒有發生”,而是由Selector代其詢問。 - 實現不同操作系統的支持:
之前已經提到過,多路復用IO技術 是需要操作系統進行支持的,其特點就是操作系統可以同時掃描同一個端口上不同網絡連接的時間。所以作為上層的JVM,必須要為不同操作系統的多路復用IO實現編寫不同的代碼。
通過上文的描述,我們知道了多路復用IO技術是操作系統的內核實現。在不同的操作系統,甚至同一系列操作系統的版本中所實現的多路復用IO技術都是不一樣的。那么作為跨平臺的JAVA JVM來說如何適應多種多樣的多路復用IO技術實現呢?面向對象的威力就顯現出來了:無論使用哪種實現方式,他們都會有“選擇器”、“通道”、“緩存”這幾個操作要素,那么可以為不同的多路復用IO技術創建一個統一的抽象組,并且為不同的操作系統進行具體的實現。JAVA NIO中對各種多路復用IO的支持,主要的基礎是java.nio.channels.spi.SelectorProvider抽象類,其中的幾個主要抽象方法包括:
-
public abstract DatagramChannel openDatagramChannel():創建和這個操作系統匹配的UDP 通道實現。
-
public abstract AbstractSelector openSelector():創建和這個操作系統匹配的NIO選擇器,就像上文所述,不同的操作系統,不同的版本所默認支持的NIO模型是不一樣的。
-
public abstract ServerSocketChannel openServerSocketChannel():創建和這個NIO模型匹配的服務器端通道。
-
public abstract SocketChannel openSocketChannel():創建和這個NIO模型匹配的TCP Socket套接字通道(用來反映客戶端的TCP連接)
多路復用IO的優缺點:
- 不用再使用多線程來進行IO處理了(包括操作系統內核IO管理模塊和應用程序進程而言)。當然實際業務的處理中,應用程序進程還是可以引入線程池技術的
- 同一個端口可以處理多種協議,例如,使用ServerSocketChannel測測的服務器端口監聽,既可以處理TCP協議又可以處理UDP協議。
- 操作系統級別的優化:多路復用IO技術可以是操作系統級別在一個端口上能夠同時接受多個客戶端的IO事件。同時具有之前我們講到的阻塞式同步IO和非阻塞式同步IO的所有特點。Selector的一部分作用更相當于“輪詢代理器”。
- 都是同步IO:目前我們介紹的 阻塞式IO、非阻塞式IO甚至包括多路復用IO,這些都是基于操作系統級別對“同步IO”的實現。
我們一直在說“同步IO”,一直都沒有詳細說,什么叫做“同步IO”。實際上一句話就可以說清楚:只有上層(包括上層的某種代理機制)系統詢問我是否有某個事件發生了,否則我不會主動告訴上層系統事件發生了。很明顯,這里是可以繼續優化的。
4. 異步IO(真正的NIO,AIO)
上述阻塞式同步IO、非阻塞式同步IO、多路復用IO 說明了IO模型是由操作系統提供支持,且這三種IO模型都是同步IO,都是采用的“應用程序不詢問我,我絕不會主動通知”的方式。
異步IO則是采用“訂閱-通知”模式:即應用程序向操作系統注冊IO監聽,然后繼續做自己的事情。當操作系統發生IO事件,并且準備好數據后,在主動通知應用程序,觸發相應的函數:
和同步IO一樣,異步IO也是由操作系統進行支持的。微軟的windows系統提供了一種異步IO技術:IOCP(I/O Completion Port,I/O完成端口);Linux下由于沒有這種異步IO技術,可以使用的是epoll對異步IO進行模擬。
總結
以上是生活随笔為你收集整理的系统间通信4:基本IO通信模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IM即时通讯服务将成联结谷歌、雅虎纽带(
- 下一篇: 机器学习资源-Harvard Ph.D