1. 程式人生 > >淺談 BIO和NIO和AIO 區別

淺談 BIO和NIO和AIO 區別

引言

BIO和NIO是兩種不同的網路通訊模型,現如今NIO已經大量應用在Jetty、ZooKeeper、Netty等開源框架中。

一個面向流、一個面向緩衝區

一個是阻塞式的、一個非阻塞

一個沒有io多路複用器、一個有

下面通過一個例子解釋兩者區別:

假設當前服務端程式需要同時從與多個客戶端建立的連線讀取資料。

使用BIO

如果採用阻塞式IO,單執行緒情況下,處理者執行緒可能阻塞在其中一個套接字的read上,導致另一個套接字即使準備好了資料也無法處理,這個時候解決的方法就是針對每一個套接字,都新建一個執行緒處理其資料讀取。

所以說,在BIO工作模式下,服務端程式要想同時處理多個套接字的資料讀取,在等待接收連線請求的主執行緒之外,還要為每一個建立好的連線分配一個新的執行緒進行處理。

使用NIO

輪詢方式

如果將套接字讀操作換成非阻塞的,那麼只需要一個執行緒就可以同時處理套接字,每次檢查一個套接字,有資料則讀取,沒有則檢查下一個,因為是非阻塞的,所以執行read操作時若沒有資料準備好則立即返回,不會發生阻塞。

I/O多路複用

這種輪詢的方式缺點是浪費CPU資源,大部分時間可能都是無資料可讀的,不必仍不間斷的反覆執行read操作,I/O多路複用(IOmultiplexing)是一種更好的方法,呼叫select函式時,其內部會維護一張監聽的套接字的列表,其會一直阻塞直到其中某一個套接字有資料準備好才返回,並告訴是哪個套接字可讀,這時再呼叫該套接字的read函式效率更高。

所以基本可以認為 “NIO = I/O多路複用 + 非阻塞式I/O”,大部分情況下是單執行緒,但也有超過一個執行緒實現NIO的情況

NIO三種模型

上面所講到的只需要一個執行緒就可以同時處理多個套接字,這只是其中的一種單執行緒模型,是一種較為極端的情況,NIO主要包含三種執行緒模型:

1) Reactor單執行緒模型

2) Reactor多執行緒模型

3)主從Reactor多執行緒模型

Reactor單執行緒模型:

單個執行緒完成所有事情包括接收客戶端的TCP連線請求,讀取和寫入套接字資料等。

對於一些小容量應用場景,可以使用單執行緒模型。但是對於高負載、大併發的應用卻不合適,主要原因如下:

1) 一個NIO執行緒同時處理成百上千的鏈路,效能上無法支撐,即便NIO執行緒的CPU負荷達到100%,也無法滿足海量訊息的編碼、解碼、讀取和傳送;

2) 當NIO執行緒負載過重之後,處理速度將變慢,這會導致大量客戶端連線超時,超時之後往往會進行重發,這更加重了NIO執行緒的負載,最終會導致大量訊息積壓和處理超時,NIO執行緒會成為系統的效能瓶頸;

3) 可靠性問題:一旦NIO執行緒意外跑飛,或者進入死迴圈,會導致整個系統通訊模組不可用,不能接收和處理外部訊息,造成節點故障。

為了解決這些問題,演進出了Reactor多執行緒模型。

Reactor多執行緒模型:

Rector多執行緒模型與單執行緒模型最大的區別就是有一組NIO執行緒處理真實的IO操作。

Reactor多執行緒模型的特點:

1) 有專門一個NIO執行緒-Acceptor執行緒用於監聽服務端,接收客戶端的TCP連線請求;

2) 網路IO操作-讀、寫等由一個NIO執行緒池負責,執行緒池可以採用標準的JDK執行緒池實現,它包含一個任務佇列和N個可用的執行緒,由這些NIO執行緒負責訊息的讀取、解碼、編碼和傳送;

3) 1個NIO執行緒可以同時處理N條鏈路,但是1個鏈路只對應1個NIO執行緒,防止發生併發操作問題。

在絕大多數場景下,Reactor多執行緒模型都可以滿足效能需求;但是,在極特殊應用場景中,一個NIO執行緒負責監聽和處理所有的客戶端連線可能會存在效能問題。例如百萬客戶端併發連線,或者服務端需要對客戶端的握手訊息進行安全認證,認證本身非常損耗效能。在這類場景下,單獨一個Acceptor執行緒可能會存在效能不足問題,為了解決效能問題,產生了第三種Reactor執行緒模型-主從Reactor多執行緒模型。

即從單執行緒中由一個執行緒即監聽連線事件、讀寫事件、由完成資料讀寫,拆分為由一個執行緒專門監聽各種事件,再由專門的執行緒池負責處理真正的IO資料讀寫。

主從Reactor多執行緒模型

主從Reactor執行緒模型與Reactor多執行緒模型的最大區別就是有一組NIO執行緒處理連線、讀寫事件。

主從Reactor執行緒模型的特點是:服務端用於接收客戶端連線的不再是個1個單獨的NIO執行緒,而是一個獨立的NIO執行緒池。Acceptor接收到客戶端TCP連線請求處理完成後(可能包含接入認證等),將新建立的SocketChannel註冊到IO執行緒池(sub reactor執行緒池)的某個IO執行緒上,由它負責SocketChannel的讀寫和編解碼工作。Acceptor執行緒池僅僅只用於客戶端的登陸、握手和安全認證,一旦鏈路建立成功,就將鏈路註冊到後端subReactor執行緒池的IO執行緒上,由IO執行緒負責後續的IO操作。

即從多執行緒模型中由一個執行緒來監聽連線事件和資料讀寫事件,拆分為一個執行緒監聽連線事件,執行緒池的多個執行緒監聽已經建立連線的套接字的資料讀寫事件,另外和多執行緒模型一樣有專門的執行緒池處理真正的IO操作。

各自適用場景

NIO適用場景

伺服器需要支援超大量長時間連線。比如10000個連線以上,並且每個客戶端並不會頻繁地傳送太多資料。例如總公司的一箇中心伺服器需要收集全國便利店各個收銀機的交易資訊,只需要少量執行緒按需處理維護的大量長期連線。

Jetty、Mina、Netty、ZooKeeper等都是基於NIO方式實現。

BIO適用場景

適用於連線數目比較小,並且一次傳送大量資料的場景,這種方式對伺服器資源要求比較高,併發侷限於應用中。

下面一個例子是我看過的一個講述的很貼切的例子:   

一輛從 A 開往 B 的公共汽車上,路上有很多點可能會有人下車。司機不知道哪些點會有哪些人會下車,對於需要下車的人,如何處理更好?   

1. 司機過程中定時詢問每個乘客是否到達目的地,若有人說到了,那麼司機停車,乘客下車。 ( 類似阻塞式 )   

2. 每個人告訴售票員自己的目的地,然後睡覺,司機只和售票員互動,到了某個點由售票員通知乘客下車。 ( 類似非阻塞 )     

很顯然,每個人要到達某個目的地可以認為是一個執行緒,司機可以認為是 CPU 。在阻塞式裡面,每個執行緒需要不斷的輪詢,上下文切換,以達到找到目的地的結果。而在非阻塞方式裡,每個乘客 ( 執行緒 ) 都在睡覺 ( 休眠 ) ,只在真正外部環境準備好了才喚醒,這樣的喚醒肯定不會阻塞。  

相關推薦

BIONIOAIO 區別應用場景

前邊簡單介紹過IO的基本情況  Java IO流 簡單回顧 對於IO我們應該非常熟悉了,IO不僅僅針對檔案的操作,網路程式設計socket的通訊,就是IO操作。 輸入、輸出流(InputStream、OutputStream)用於讀取或寫入位元組,如操作圖片、視訊等。

BIONIOAIO 區別

引言 BIO和NIO是兩種不同的網路通訊模型,現如今NIO已經大量應用在Jetty、ZooKeeper、Netty等開源框架中。 一個面向流、一個面向緩衝區 一個是阻塞式的、一個非阻塞 一個沒有io多路複用器、一個有 下面通過一個例子解釋兩者區別: 假設當前服

BIONIOAIO區別、具體實現

一:理解同步:同步就是在發出一個*呼叫*時,在沒有得到結果之前,該*呼叫*就不返回,但是一旦呼叫返回,就得到返回值了。簡單的為:就是由*呼叫者*主動等待這個*呼叫*的結果。 二:非同步:*呼叫*在發出之後,這個呼叫就直接返回了,所以沒有返回結果;換句話說,當一個非同步過程呼

Java中BIONIOAIO區別應用場景

    學習IO,首先要明白四個東西。 1.同步         java自己去處理io。 2.非同步 java將io交給作業系統去處理,告訴快取區大小,處理完成回撥。 3.阻塞  使用阻塞IO時,Java呼叫會一直阻塞到讀寫完成才返回。 4.非阻塞 使用非阻塞IO時,如果不能立馬讀寫,Java呼叫會馬上返

BIONIOAIO區別(簡明版)

      一:事件分離器         在IO讀寫時,把 IO請求 與 讀寫操作 分離調配進行,需要用到事件分離器。根據處理機制的不同,事件分離器又分為:同步的Reactor和非同步的Proactor。         Reactor模型: - 應用程式

Java中BIONIOAIO區別應用場景

最近一直在準備面試,為了使自己的Java水平更上一個檔次,拜讀了李林峰老師的《Netty權威指南》,瞭解了Java關於IO的發展和最新的技術,真是受益匪淺,現在把我總結的關於BIO、NIO和AIO的區別

BIONIOAIO區別

  IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、非同步非阻塞的AIO。 一、BIO 在JDK1.4出來之前,我們建立網路連線的時候採用BIO模式,需要先在服務端啟動一個ServerSocket,然後在客戶端啟動Socket來對服務端進行通訊,預設情況

talent-aio的使用原理講解系列(一)--java bionioaio的io模型區別講解

   2017年春季開源中國要說最火的開源專案,即時通訊框架敢說第一,沒人敢說第二,當然現在是3月10日,它還能否火熱一年讓我們拭目以待。    雖然我不是talent-aio的作者,但也是掛名的開發

cookie,sessionStoragelocalStorage區別

一次 flash htm ddb coo 清除 rem 限制 web服務器 在客戶端存儲數據可以使用的技術有如下四種: Cookie技術:瀏覽器兼容性好,但操作比較復雜,需要程序員自己封裝,源生的Cookie接口不友好 H5 WebStorage:不能超過8

Mybatis中的 ${ } #{ }的區別

mybatis sql註入 語句 nbsp 之前 com pre 預編譯 sql 語句 一、舉例說明 1 select * from user where name = "dato"; 2 3 select * from user where name = #

Mysql中wherehaving的區別

where和having的區別一、誤區:不要錯誤的認為having和group by 必須配合使用.二、where和having用法解析:1、 where和having都可以使用的場景: select goods_price,goods_name from goods where goods_price &g

C#NET抽象類接口的區別

直接 bstr 訪問 rtu 例如 virtual 索引 AC 特性 一、抽象類: 在類聲明中使用abstract修飾符的類稱為抽象類。含有一個或一個以上的抽象成員的類,必須定義為抽象類。當方法聲明包含abstract修飾符時,稱該方法為抽象方法,雖然抽象方法同時隱含為虛擬

線程runnablecallable的使用及區別

RoCE div unable 邏輯 exc pan service 但是 submit 線程使用比較廣泛,但實際上一般項目很少用上線程,線程常用於優化復雜的程序執行流程,把一些與業務關系關系不大但是必須要執行的流程使用線程的方式讓子線程去執行,主流程只返回跟業務有關的信息

BIONIOAIO

IO的方式通常分為幾種,同步阻塞的BIO、同步非阻塞的NIO、非同步非阻塞的AIO。 一、BIO      在JDK1.4出來之前,我們建立網路連線的時候採用BIO模式,需要先在服務端啟動一個ServerSocket,然後在客戶端啟動Socket來對服務端進行通訊,預設情

BIONIOAIO講的很明白的文章

到底什麼是“IO Block” 很多人說BIO不好,會“block”,但到底什麼是IO的Block呢?考慮下面兩種情況: 用系統呼叫read從socket裡讀取一段資料 用系統呼叫read從一個磁碟檔案讀取一段資料到記憶體 如果你的直覺告訴你,這兩種都算“Block”,

【轉載】JavaScript,letvar定義變數的區別

瞭解JS與ES5與ES6區別 JS語言  JavaScript一種動態型別、弱型別、基於原型的客戶端指令碼語言,用來給HTML網頁增加動態功能。 動態: 在執行時確定資料型別。變數使用之前不需要型別宣告,通常變數的型別是被賦值的那個值的型別。 弱類: 計算時可以不同型別之間對使用者透明地

結合程式碼詳細聊聊BIONIOAIO

作者:大寬寬 1、到底什麼是“IO Block” 很多人說BIO不好,會“block”,但到底什麼是IO的Block呢?考慮下面兩種情況: 用系統呼叫read從socket裡讀取一段資料 用系統呼叫read從一個磁碟檔案讀取一段資料到記憶體 如果你的直覺告

ES的letconst及其區別

淺談ES的let和const ES6提供了let和const的新特性,同時也是新的變數宣告方式,它能解決以往var變數宣告存在的隱性弊端問題。 Let let的出現,解決了ES中塊級作用域的需求。回顧在這之前,Js並沒有沒什麼類似其他程式語言中塊級作用域的概念(

MVC,MVP MVVM 的區別

複雜的軟體必須有清晰合理的架構,否則無法開發和維護。 以下以Javascript客戶端頁面開發為例使用圖示簡單闡述三者的聯絡和區別。 需要注意的是,MVC開發模式備廣泛用於各種軟體開發中,包括網際網路的B/S模式的產品,而其他兩種模式大多數用在客戶端開發中,例如:Javascrtipt、WPF、Adn

Java的BIONIOAIO介紹

1. I/O概念理解:同步/非同步、阻塞/非阻塞 一個IO操作其實分成了兩個步驟:發起IO請求和實際的IO操作。 同步IO和非同步IO的區別就在於第二個步驟是否阻塞,如果實際的IO讀寫阻塞請求程序,那麼就是同步IO。 阻塞IO和非阻塞IO的區別在於第一步,發