天天看點

02-netty io之路-什麼是bio、nio、aio?

文章目錄

    • 1 什麼是BIO?
      • 1.1 阻塞io模型說明
      • 1.2 阻塞io線程模型說明
    • 2 什麼是NIO?
      • 2.1 非阻塞io簡介
    • 3 什麼是AIO?
      • 3.1 I/O 多路複用( IO multiplexing)
      • 3.2 異步 I/O(asynchronous IO)
      • 3.3 AIO
    • 4 io技術比較
    • 5 netty為什麼選擇NIO?而不是AIO?
    • 參考

1 什麼是BIO?

1.1 阻塞io模型說明

02-netty io之路-什麼是bio、nio、aio?
當使用者程序調用了recvfrom這個系統調用,kernel就開始了IO的第一個階段:準備資料(對于網絡IO來說,很多時候資料在一開始還沒有到達。比如,還沒有收到一個完整的UDP包。這個時候kernel就要等待足夠的資料到來)。這個過程需要等待,也就是說資料被拷貝到作業系統核心的緩沖區中是需要一個過程的。而在使用者程序這邊,整個程序會被阻塞(當然,是程序自己選擇的阻塞)。當kernel一直等到資料準備好了,它就會将資料從kernel中拷貝到使用者記憶體,然後kernel傳回結果,使用者程序才解除block的狀态,重新運作起來。
           
blocking IO的特點就是在IO執行的兩個階段都被block了。

1.2 阻塞io線程模型說明

02-netty io之路-什麼是bio、nio、aio?
  • 傳統bio程式設計中,由一個獨立的accepter線程負責監聽用戶端的連接配接請求,為每一個用戶端建立一個新的線程處理;
    缺點:模型缺乏彈性,服務端線程數與用戶端的通路數呈現1:1的關系,一旦連接配接變多,并發量大,性能急劇下降;

僞異步io模型:

02-netty io之路-什麼是bio、nio、aio?

僞異步io模型将用戶端的socket請求封裝成一個task,投遞到後端線程池進行處理,不會導緻伺服器随并發通路增加而出現資源耗盡和當機;

缺點:僅優化了線程模型,沒有從根本上解決io阻塞問題,當io故障,讀寫操作都會發生阻塞,

阻塞隊列會導緻後續操作全部阻塞,無法接收新的請求

2 什麼是NIO?

2.1 非阻塞io簡介

02-netty io之路-什麼是bio、nio、aio?
當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它并不會block使用者程序,而是立刻傳回一個error。從使用者程序角度講 ,它發起一個read操作後,并不需要等待,而是馬上就得到了一個結果。使用者程序判斷結果是一個error時,它就知道資料還沒有準備好,于是它可以再次發送read操作。一旦kernel中的資料準備好了,并且又再次收到了使用者程序的system call,那麼它馬上就将資料拷貝到了使用者記憶體,然後傳回。

           
是以,nonblocking IO的特點是使用者程序需要不斷的主動詢問kernel資料好了沒有。

非阻塞io做了什麼?

  • 保證連接配接異步

    —>通過多路複用器保證用戶端連接配接不被阻塞;
  • 讀寫操作異步

    —>不是一直等待資料,而是利用緩沖區機制,有則處理,無則不等待處理其他;
  • 線程模型優化

    —>通過selector線程同時處理上萬個連接配接;

3 什麼是AIO?

3.1 I/O 多路複用( IO multiplexing)

02-netty io之路-什麼是bio、nio、aio?

當使用者程序調用了select,那麼整個程序會被block

,而同時,kernel會“監視”所有select負責的socket,當任何一個socket中的資料準備好了,select就會傳回。這個時候使用者程序再調用read操作,将資料從kernel拷貝到使用者程序。

是以,I/O 多路複用的特點是通過一種機制一個程序能同時等待多個檔案描述符,而這些檔案描述符(套接字描述符)其中的任意一個進入讀就緒狀态,select()函數就可以傳回。

這個圖和blocking IO的圖其實并沒有太大的不同,事實上,還更差一些。因為這裡需要使用兩個system call (select 和 recvfrom),而blocking IO隻調用了一個system call (recvfrom)。但是,用select的優勢在于它可以同時處理多個connection。

是以,如果處理的連接配接數不是很高的話,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延遲還更大。select/epoll的優勢并不是對于單個連接配接能處理得更快,而是在于能處理更多的連接配接。)

在IO multiplexing Model中,實際中,對于每一個socket,一般都設定成為non-blocking,但是,如上圖所示,整個使用者的process其實是一直被block的。隻不過process是被select這個函數block,而不是被socket IO給block。

3.2 異步 I/O(asynchronous IO)

02-netty io之路-什麼是bio、nio、aio?

使用者程序發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之後,首先它會立刻傳回,是以不會對使用者程序産生任何block。然後,kernel會等待資料準備完成,然後将資料拷貝到使用者記憶體,當這一切都完成之後,kernel會給使用者程序發送一個signal,告訴它read操作完成了。

3.3 AIO

NIO2.0的異步套接字通道是真正的異步非阻塞式io,對應于unix網絡程式設計中的事件驅動i/o.

它不需要多路複用器對注冊的通道進行輪詢操作就可以實作異步讀寫,簡化了NIO的程式設計模型

AIO做了什麼:

  • 異步檔案通道

    :
  • 異步套接字通道

4 io技術比較

02-netty io之路-什麼是bio、nio、aio?

可以發現non-blocking IO和asynchronous IO的差別還是很明顯的。在non-blocking IO中,

雖然程序大部分時間都不會被block,但是它仍然要求程序去主動的check

,并且當資料準備完成以後,也需要程序主動的再次調用recvfrom來将資料拷貝到使用者記憶體。而asynchronous IO則完全不同。它就像是使用者程序将整個IO操作交給了他人(

kernel

)完成,然後他人做完後發信号通知。

在此期間,使用者程序不需要去檢查IO操作的狀态,也不需要主動的去拷貝資料。

5 netty為什麼選擇NIO?而不是AIO?

我們首先來看看netty創始人trustlin對于這個問題給出的回答:

02-netty io之路-什麼是bio、nio、aio?

這是trustlin在2014年的github上給出的回答,原因是linux的異步aio實作仍然采用的是epoll模型,與非阻塞式io沒有本質差別,但是目前netty或者linu對于epoll的實作如何,還有待進一步分析,後續研究再說明!

參考

本文參考内容

https://www.cnblogs.com/yxmx/articles/1600736.html

https://www.cnblogs.com/aspirant/p/9166944.html

https://segmentfault.com/a/1190000003063859

http://www.52im.net/thread-566-1-1.html

https://segmentfault.com/a/1190000003063859