溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Nodejs中的非阻塞異步IO是什么

發(fā)布時(shí)間:2022-12-08 09:40:11 來源:億速云 閱讀:97 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“Nodejs中的非阻塞異步IO是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Nodejs中的非阻塞異步IO是什么”吧!

我們以網(wǎng)絡(luò)請(qǐng)求IO為例,首先介紹服務(wù)端處理一次完整的網(wǎng)絡(luò)IO請(qǐng)求的典型流程:

Nodejs中的非阻塞異步IO是什么

應(yīng)用程序獲得一個(gè)操作結(jié)果,通常包括兩個(gè)不同的階段:

  • 等待數(shù)據(jù)準(zhǔn)備好

  • 從內(nèi)核向進(jìn)程復(fù)制數(shù)據(jù)

以下,我們以 recvfrom 函數(shù)為例,解釋說明各種IO模型

阻塞式 I/O 模型(blocking I/O)

阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起,調(diào)用線程只有在等待系統(tǒng)內(nèi)核層面所有操作完成之后,調(diào)用才會(huì)結(jié)束。

阻塞I/O造成了cpu的等待I/O,浪費(fèi)了CPU的時(shí)間片。

Nodejs中的非阻塞異步IO是什么

非阻塞式I/O模型(non-blocking I/O)

相比于前者,非阻塞I/O不帶數(shù)據(jù)直接返回,要獲取數(shù)據(jù),還需要通過文件描述符再次嘗試讀取數(shù)據(jù)

Nodejs中的非阻塞異步IO是什么

阻塞調(diào)用得到返回(并不是真實(shí)的期待數(shù)據(jù))之后,CPU時(shí)間片可以用于處理其他的事情,可以明顯提升性能。

但是隨之而來的問題是,之前的操作并不是一次完整的I/O,返回得到的結(jié)果不是期望得到的業(yè)務(wù)數(shù)據(jù),而僅僅是異步調(diào)用狀態(tài)。

為了獲取完整的數(shù)據(jù),應(yīng)用程序需要重復(fù)調(diào)用IO操作來確認(rèn)操作是否已經(jīng)完成,這種操作我們稱之為輪詢,常見的幾種輪詢策略如下

忙輪詢

這是最原始,也是性能最低的一種方式,通過重復(fù)調(diào)用來檢查I/O狀態(tài)達(dá)到獲取完整數(shù)據(jù)的目的

Nodejs中的非阻塞異步IO是什么

優(yōu)點(diǎn):編程簡(jiǎn)單

缺點(diǎn):CPU一直耗費(fèi)在輪詢上,同時(shí)影響服務(wù)器性能,因?yàn)槟爿喸冎蠓?wù)器還要進(jìn)行作答

I/O復(fù)用模型(I/O multiplexing)

Nodejs中的非阻塞異步IO是什么

在 I/O 復(fù)用模型中,會(huì)用到 Select 或 Poll 函數(shù)或 Epoll 函數(shù)(Linux 2.6 以后的內(nèi)核開始支持),這兩個(gè)函數(shù)也會(huì)使進(jìn)程阻塞,但是和阻塞 I/O 有所不同。

這三個(gè)函數(shù)可以同時(shí)阻塞多個(gè) I/O 操作,而且可以同時(shí)對(duì)多個(gè)讀操作,多個(gè)寫操作的 I/O 函數(shù)進(jìn)行檢測(cè),直到有數(shù)據(jù)可讀或可寫時(shí),才真正調(diào)用 I/O 操作函數(shù)。

三種I/O復(fù)用機(jī)制的區(qū)別如下

  • select

由于select采用1024長度的數(shù)組來存儲(chǔ)文件狀態(tài),因此最多可以同時(shí)檢測(cè)1024個(gè)文件描述符

  • poll

相比select略有改進(jìn),采用鏈表避免了1024的長度限制,并且能避免不需要的遍歷檢查,相比select性能稍有改善

  • epoll/kqueue

是linux下效率最高的I/O事件通知機(jī)制,輪詢時(shí)如果沒有檢測(cè)到I/O事件,將會(huì)進(jìn)行休眠,直到事件發(fā)生將線程喚醒。它是真正利用了事件通知,執(zhí)行回調(diào),而不是遍歷(文件描述符)查詢,因此不會(huì)浪費(fèi)CPU

Nodejs中的非阻塞異步IO是什么

小結(jié):本質(zhì)上說,輪詢?nèi)匀皇且环N同步操作,因?yàn)閼?yīng)用程序仍然在等待I/O完全返回,等待期間要么遍歷文件描述狀態(tài),要么休眠等待事件的發(fā)生。

信號(hào)驅(qū)動(dòng)式I/O模型(signal-driven I/O)

Nodejs中的非阻塞異步IO是什么

在信號(hào)驅(qū)動(dòng)式 I/O 模型中,應(yīng)用程序使用信號(hào)驅(qū)動(dòng) I/O,并安裝一個(gè)信號(hào)處理函數(shù),進(jìn)程繼續(xù)運(yùn)行并不阻塞。

當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),程序會(huì)收到一個(gè) SIGIO 信號(hào),可以在信號(hào)處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)。

小結(jié):到此為止,信號(hào)驅(qū)動(dòng)式I/O模型是更加符合我們的異步需求的,程序會(huì)在等待數(shù)據(jù)的過程中異步執(zhí)行其他的業(yè)務(wù)邏輯。

但是?。?! 在數(shù)據(jù)從內(nèi)核復(fù)制到用戶空間過程中依然是阻塞的,并不能算是一場(chǎng)徹底的革命(異步)。

理想中的(Node)非阻塞異步I/O

我們理想中的異步I/O應(yīng)該是應(yīng)用程序發(fā)起非阻塞調(diào)用,無需通過輪詢的方式進(jìn)行數(shù)據(jù)獲取,更沒有必要在數(shù)據(jù)拷貝階段進(jìn)行無謂的等待,而是能夠在I/O完成之后,通過信號(hào)或者回調(diào)函數(shù)的方式傳遞給應(yīng)用程序,在此期間應(yīng)用程序可以執(zhí)行其他業(yè)務(wù)邏輯。

Nodejs中的非阻塞異步IO是什么

實(shí)際的異步I/O

實(shí)際上,linux平臺(tái)下原生支持了異步I/O(AIO),但是目前 AIO 并不完善,因此在 Linux 下實(shí)現(xiàn)高并發(fā)網(wǎng)絡(luò)編程時(shí)都是以 I/O 復(fù)用模型為主。

而Windows 下通過 IOCP 實(shí)現(xiàn)了真正的異步 I/O。

多線程模擬異步I/O

linux平臺(tái)下,Node利用線程池,通過讓部分線程進(jìn)行阻塞I/O或者非阻塞I/O+輪詢的方式完成數(shù)據(jù)獲取,讓某一個(gè)單獨(dú)的線程進(jìn)行計(jì)算,通過線程之間的通信,將I/O結(jié)果進(jìn)行傳遞,這樣便實(shí)現(xiàn)了異步I/O的模擬。

其實(shí)Windows平臺(tái)下的IOCP異步異步方案底層也是采用線程池的方式實(shí)現(xiàn)的,所不同的是,后者的線程池是由系統(tǒng)內(nèi)核進(jìn)行托管的。

我們常說Node是單線程的,但其實(shí)只能說是JS執(zhí)行在單線程中,無論是*nix還是windows平臺(tái),底層都是利用線程池來完成I/O操作。

感謝各位的閱讀,以上就是“Nodejs中的非阻塞異步IO是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Nodejs中的非阻塞異步IO是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI