這篇文章主要為大家展示了“Node中的I/O模型有哪些”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學習一下“Node中的I/O模型有哪些”這篇文章吧。
為嘉魚等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及嘉魚網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站制作、成都網(wǎng)站建設(shè)、嘉魚網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
我們以網(wǎng)絡(luò)請求IO為例,首先介紹服務(wù)端處理一次完整的網(wǎng)絡(luò)IO請求的典型流程:
應(yīng)用程序獲得一個操作結(jié)果,通常包括兩個不同的階段:
等待數(shù)據(jù)準備好
從內(nèi)核向進程復(fù)制數(shù)據(jù)
以下,我們以 recvfrom
函數(shù)為例,解釋說明各種IO模型
阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當前線程會被掛起,調(diào)用線程只有在等待系統(tǒng)內(nèi)核層面所有操作完成之后,調(diào)用才會結(jié)束。
阻塞I/O造成了cpu的等待I/O,浪費了CPU的時間片。
相比于前者,非阻塞I/O不帶數(shù)據(jù)直接返回,要獲取數(shù)據(jù),還需要通過文件描述符再次嘗試讀取數(shù)據(jù)
非阻塞調(diào)用得到返回(并不是真實的期待數(shù)據(jù))之后,CPU時間片可以用于處理其他的事情,可以明顯提升性能。
但是隨之而來的問題是,之前的操作并不是一次完整的I/O,返回得到的結(jié)果不是期望得到的業(yè)務(wù)數(shù)據(jù),而僅僅是異步調(diào)用狀態(tài)。
為了獲取完整的數(shù)據(jù),應(yīng)用程序需要重復(fù)調(diào)用IO操作來確認操作是否已經(jīng)完成,這種操作我們稱之為輪詢,常見的幾種輪詢策略如下
這是最原始,也是性能最低的一種方式,通過重復(fù)調(diào)用來檢查I/O狀態(tài)達到獲取完整數(shù)據(jù)的目的
優(yōu)點:編程簡單
缺點:CPU一直耗費在輪詢上,同時影響服務(wù)器性能,因為你輪詢之后服務(wù)器還要進行作答
在 I/O 復(fù)用模型中,會用到 Select 或 Poll 函數(shù)或 Epoll 函數(shù)(Linux 2.6 以后的內(nèi)核開始支持),這兩個函數(shù)也會使進程阻塞,但是和阻塞 I/O 有所不同。
這三個函數(shù)可以同時阻塞多個 I/O 操作,而且可以同時對多個讀操作,多個寫操作的 I/O 函數(shù)進行檢測,直到有數(shù)據(jù)可讀或可寫時,才真正調(diào)用 I/O 操作函數(shù)。
三種I/O復(fù)用機制的區(qū)別如下
select
由于select采用1024長度的數(shù)組來存儲文件狀態(tài),因此最多可以同時檢測1024個文件描述符
poll
相比select略有改進,采用鏈表避免了1024的長度限制,并且能避免不需要的遍歷檢查,相比select性能稍有改善
epoll/kqueue
是linux下效率最高的I/O事件通知機制,輪詢時如果沒有檢測到I/O事件,將會進行休眠,直到事件發(fā)生將線程喚醒。它是真正利用了事件通知,執(zhí)行回調(diào),而不是遍歷(文件描述符)查詢,因此不會浪費CPU
小結(jié):本質(zhì)上說,輪詢?nèi)匀皇且环N同步操作,因為應(yīng)用程序仍然在等待I/O完全返回,等待期間要么遍歷文件描述狀態(tài),要么休眠等待事件的發(fā)生。
在信號驅(qū)動式 I/O 模型中,應(yīng)用程序使用信號驅(qū)動 I/O,并安裝一個信號處理函數(shù),進程繼續(xù)運行并不阻塞。
當數(shù)據(jù)準備好時,程序會收到一個 SIGIO 信號,可以在信號處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)。
小結(jié):到此為止,信號驅(qū)動式I/O模型是更加符合我們的異步需求的,程序會在等待數(shù)據(jù)的過程中異步執(zhí)行其他的業(yè)務(wù)邏輯。
但是?。?!在數(shù)據(jù)從內(nèi)核復(fù)制到用戶空間過程中依然是阻塞的,并不能算是一場徹底的革命(異步)。
我們理想中的異步I/O應(yīng)該是應(yīng)用程序發(fā)起非阻塞調(diào)用,無需通過輪詢的方式進行數(shù)據(jù)獲取,更沒有必要在數(shù)據(jù)拷貝階段進行無謂的等待,而是能夠在I/O完成之后,通過信號或者回調(diào)函數(shù)的方式傳遞給應(yīng)用程序,在此期間應(yīng)用程序可以執(zhí)行其他業(yè)務(wù)邏輯。
實際上,linux平臺下原生支持了異步I/O(AIO),但是目前 AIO 并不完善,因此在 Linux 下實現(xiàn)高并發(fā)網(wǎng)絡(luò)編程時都是以 I/O 復(fù)用模型為主。
而Windows 下通過 IOCP 實現(xiàn)了真正的異步 I/O。
linux平臺下,Node利用線程池,通過讓部分線程進行阻塞I/O或者非阻塞I/O+輪詢的方式完成數(shù)據(jù)獲取,讓某一個單獨的線程進行計算,通過線程之間的通信,將I/O結(jié)果進行傳遞,這樣便實現(xiàn)了異步I/O的模擬。
其實Windows平臺下的IOCP異步異步方案底層也是采用線程池的方式實現(xiàn)的,所不同的是,后者的線程池是由系統(tǒng)內(nèi)核進行托管的。
我們常說Node是單線程的,但其實只能說是JS執(zhí)行在單線程中,無論是*nix還是windows平臺,底層都是利用線程池來完成I/O操作。
以上是“Node中的I/O模型有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!