五分鐘掌握同步異步I/O同步阻塞同步非阻塞異步阻塞異步非阻塞
網絡通訊原理
在講I\O的時候,先簡單講下網絡通訊原理。
網絡通訊四要素:本機的IP地址、子網掩碼、網關的IP地址和DNS的IP地址。
四要素有兩種方式:一是靜態獲取,即手動配置;二是動態獲取,即通過DHCP(Dynamic Host Configuration Protocol,動態主機配置協議)獲取
網絡通訊的過程
- 瀏覽器解析網址(IP地址+協議+端口號),通過訪問DNS域名系統服務器(基於UDP)獲得IP地址
- 生成HTTP消息並轉交給Socket抽象層
- 再經過傳輸層,網絡層,鏈路層等。細節先省略。可以參照:網絡通訊的的整體流程
Socket起源於UNIX,在UNIX“一切皆文件”的哲學思想下,Socket是一種從打開,到完成讀、寫操作,最後關閉的模式,服務器和客戶端各自維護一個“文件”,在建立連接打開文件後,可以向自己的文件寫入內容供對方讀取或者讀取對方的內容,通信結束時關閉文件。
I/O
用戶進程中的一次完整I/O交互流程分爲兩階段,首先是經過內核空間,也就是由操作系統處理;緊接着就是到用戶空間,也就是交由應用程序。
通俗地將,可以將I/O分爲兩步:第一步是等待;第二步是數據搬遷。
阻塞I/O模型
阻塞I/O模型特點:在I\O執行的兩個階段(等待數據和拷貝數據)都被阻塞。
下圖中紅色部分都是阻塞。
典型應用:阻塞Socket、Java BIO
優點:阻塞掛起不消耗CPU資源
非阻塞I/O模型
相比較阻塞I/O,多了一個輪詢訪問內核是否存在。
典型應用:Socket設置NON_BLOCK
缺點:輪詢調用,消耗CPU資源
多路複用I/O模型
多路複用I/O模型和阻塞I/O模型並沒有太大的不同,事實上,還更差一些,因爲這裏需要使用兩次系統調用(select和recvfrom),而阻塞I/O模型只有一次系統調用(recvfrom)。但是,用Selector的優勢在於它可以同時處理多個連接,所以如果處理的連接數不是很多,多路複用I\O模型並不一定比使用多線程加阻塞I\O性能要好,可能延時更大。優勢在於能處於更多的連接。
典型應用:Java NIO,Nginx(epoll,poll,select)
信號驅動I\O模型
信號驅動I/O是指進程預先告知內核,向內核註冊一個信號處理函數,然後用戶進程返回不阻塞,當內核數據就緒時會發送一個信號給進程,用戶進程便在信號處理函數中調用I/O讀取數據。
應用場景比較少。
異步I/O模型
工作機制:告知內核啓動某個操作,並讓內核在整個操作完成後通知我們。
與信號驅動I/O模型的區別:信號驅動I/O模型是由內核通知我們何時可以啓動一個I/O操作,這個I/O操作由用戶自定義的信號函數來實現,而異步I/O模型由內核告知我們I/O操作何時完成
典型應用:Java 7 AIO,高性能服務器應用
不阻塞,數據一步到位,採用Proactor模式
缺點:需要操作系統底層支持,Linux2.5內核首現 2.6產的內部標準特性
易於混淆的概念
- 同步阻塞
- 同步非阻塞
- 異步阻塞
- 異步非阻塞
同步和異步的區別:
同步:應用程序主動發起請求詢問狀態(輪詢)
異步:服務方會主動通知請求方
阻塞和非阻塞的區別:
阻塞:等待返回數據之前,當前的線程是掛起狀態
非阻塞:等待返回數據之前,當前的線程是運行狀態,可以繼續處理其他任務
列子:
(1)這個時候,如果我們一直在店裏面什麼都不幹,一直等待直到洗完照片,這個過程就叫同步阻塞。
(2)當然,大部分人很少這麼幹,更多的是大家拿起手機開始看電視,看一會兒就會問老闆洗完沒,老闆說沒洗完,然後接着看,再過一會兒接着問,直到照片洗完,這個過程就叫同步非阻塞。
(3)由於店裏生意太好了,越來越多的人過來拍,店裏面快沒地方坐了,老闆說你把手機號留下,我一會兒洗好了就打電話告訴你過來取,然後你去外面找了一個長凳開始躺着睡覺等待老闆打電話,什麼都不幹,這個過程就叫異步阻塞(實際不應用)。
(4)當然實際情況是,大家可能會先去逛街或者喫飯,或者做其他活動,這樣一來,兩不耽誤,這個過程就叫異步非阻塞(效率最高)。
各I/O模型的對比與總結
阻塞程度:阻塞I/O>非阻塞I/O>多路複用I/O>信號驅動I/O>異步I/O,效率是由低到高的。
BIO、NIO、AIO
BIO:一個連接只用一個線程來處理。
NIO:單線程管理多個連接。緩衝區(Buffer)、選擇器(Selector)和通道(Channel)
AIO:異步I/O,把I/O讀寫操作完全交給操作系統。操作系統主動通知實現異步。
BIO | NIO | AIO |
---|---|---|
面向流 | 面向緩衝區 | 操作系統主動通知用戶線程 |
阻塞I\O | 非阻塞I\O |
Proactor設計模式 |
參考資料
[1]: Netty 4核心原理與手寫RPC框架實戰