原文
先說1.1總攬:
Reactor模式
Reactor模式中的協(xié)調機制Event Loop
Reactor模式中的事件分離器Event Demultiplexer
一些Event Demultiplexer處理不了的復雜I/O接口比如File I/O、DNS等
復雜I/O的解決方案
未完待續(xù)
前言nodejs和其他編程平臺的區(qū)別在于如何去處理I/O接口,我們聽一個人介紹nodejs,總是會說是一個基于v8引擎,沒有堵塞,事件驅動的語言,那這些又意味著什么呢?什么叫‘沒有堵塞’和‘事件驅動’?所有的答案都在nodejs的核心——Event Loop。
在這一系列的帖子中,我們將一起去描述什么是Event Loop,它是如何工作的,它是如何影響我們的應用的,如何充分的利用他甚至更多。為什么不用一篇代替一個系列的帖子呢,因為這樣的話,他就會變成一個很長很長的帖子,我會肯定會錯過很多東西,因此我才把它寫成一個系列,在第一篇帖子中,我將講述nodejs如何工作,如何通過I/O,他如何與其他平臺一起工作等。
nodejs工作在一個事件驅動的模型中,這個模型涉及一個事件分離器和事件循環(huán),所有的I/O請求最終將會生成一個事件完成、事件失敗或者喚醒其他事件的結果。這些事件將會根據(jù)以下規(guī)則做處理:
1.事件分離器收到I/O請求,之后將這些請求委托給相應的硬件
2.曾經被處理過的請求(比如來自可讀取文件的數(shù)據(jù),來自可讀取接口的數(shù)據(jù)),事件分離器會為要進行的特殊操作添加注冊回調程序。
3.如果事件可以在事件循環(huán)中被處理,那么將有序的被執(zhí)行,直到循環(huán)為空
4.如果沒有事件在事件循環(huán)中,或者事件分離器沒有添加任何請求,這個 程序將被完成,否則,程序將從第一步在開始,進行循環(huán)操作。
這整個工程的協(xié)調機制我們叫做Event Loop
Event Loop其實是一個單線程的半無限循環(huán),為什么會說是半無限呢?因為在沒有工作需要完成的時候程序會退出。從開發(fā)者的角度來說,這些是程序退出的點。
注意:不要把Event Loop和Event Emitter弄混淆,Event Emitter和這個機制完全是不同的概念,在最后一篇帖子,我會解釋Event Emitter是如何通過Event Loop影響事件的處理。
上面的圖是對NodeJs如何工作以及展示一種被叫做Reactor Pattern的主要組件的設計模式的高級概覽。
但是真正的復雜度遠超于它,那它有多復雜呢?
Event demultiplexer不是一個在所有os平臺中解析所有I/O類型的單一組件。
Event queue在這里展示出來的不是一個單一的隊列,在其中所有類型的事件會在隊列中排隊或者從隊列中移除,并且I/O不是唯一一個要排隊的事件類型
讓我們繼續(xù)深挖
Event DemultiplexerEvent Demultiplexer并不是一個現(xiàn)實存在的組件,而是在reactor pattern中的一個抽象概念。
在現(xiàn)實中,Event Demultiplexer 在不同的系統(tǒng)中以不同的名字被實現(xiàn),比如在linux中叫做epoll, 在MacOS中叫做kqueue,在Solaris中叫event post,在window系統(tǒng)下叫做IOCP等。
nodeJS可以使用Event Demultiplexer提供的底層非阻塞、異步硬件I/O功能。
Complexities in File I/O但是令人苦惱的是,不是所有類型的I/O都可以使用Event Demultiplexer被執(zhí)行,甚至是在相同的操作系統(tǒng)中,支持不同類型的I/O也是很復雜的。
通常來說,epoll, kqueue, event ports和IOCP可以使用非阻塞的方式執(zhí)行網(wǎng)絡I/O。
但是文件I/O就復雜多了,某些系統(tǒng),比如Linux不支持完全異步的方式去訪問文件系統(tǒng),在MacOS系統(tǒng)中文件系統(tǒng)對事件的發(fā)送和接收會有限制(你可以在這里了解更多)。
為了提供完全異步而去解決所有文件系統(tǒng)的復雜性是非常復雜的,幾乎是不可能的。
Complexities in DNS和文件I/O一樣,由node API提供某些DNS的功能也存在一定的復雜性。
比如dns.lookup等Node DNS功能訪問系統(tǒng)的一些配置文件,例如nsswitch.conf、resolv.conf和/etc/hosts。
上面描述的文件系統(tǒng)復雜性也適用于dns.resolve函數(shù)。
The solution?因此,引入了一個線程池來支持I/O功能,這些功能不能由硬件異步I/O實用程序(如epoll / kqueue / event ports或IOCP)直接解決。
現(xiàn)在我們知道不是所有的I/O功能都可以在線程池中運行。nodeJS已經盡最大努力來使用非阻塞和硬件的異步I/O方式來完成大部分I/O功能,但是對于一些復雜的、阻塞的I/O還是通過引入一個線程池的方式來解決
未完待續(xù)該篇先翻譯到這,有些地方翻譯的不好請指出,過幾天我會繼續(xù)出第二篇。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/92567.html
摘要:引言作為服務器的優(yōu)勢就在于適合處理高并發(fā)的請求,對于網(wǎng)站后臺這種密集型的后臺尤其有優(yōu)勢,其核心就在于是一個異步非阻塞模型。關于異步,同步,阻塞,非阻塞這些概念,本文不做討論。另外兩個的調用時間需要判斷是否都在主線程中被執(zhí)行。 引言 node作為服務器的優(yōu)勢就在于適合處理高并發(fā)的請求,對于web網(wǎng)站后臺這種I/O密集型的后臺尤其有優(yōu)勢,其核心就在于node是一個異步非阻塞模型。關于異步,...
摘要:前端日報精選大前端公共知識梳理這些知識你都掌握了嗎以及在項目中的實踐深入貫徹閉包思想,全面理解閉包形成過程重溫核心概念和基本用法前端學習筆記自定義元素教程阮一峰的網(wǎng)絡日志中文譯回調是什么鬼掘金譯年,一個開發(fā)者的好習慣知乎專 2017-06-23 前端日報 精選 大前端公共知識梳理:這些知識你都掌握了嗎?Immutable.js 以及在 react+redux 項目中的實踐深入貫徹閉包思...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
摘要:事件處理器,則是當指定事件觸發(fā)時,執(zhí)行的一段代碼。事件循環(huán)以一個無限循環(huán)的形式啟動,存在于二進制文件里函數(shù)的最后,當沒有更多可被執(zhí)行的事件處理器時,它就退出。 前言 如果你了解過Node.js,那么你一定聽說過事件循環(huán)。你一定想知道它為什么那么特殊,并且為什么你需要關注它?此時此刻的你,可能已經寫過許多基于Express.js的后端代碼,但沒有接觸到任何的循環(huán)。 在下文中,我們會先在一...
摘要:單線程的好處簡單,處理時不會出現(xiàn)并發(fā)競爭問題異步的必要性讓用戶體驗更流暢如何實現(xiàn)異步見參考,,調用棧函數(shù)執(zhí)行上下文。單線程只能有一個并且每次只能執(zhí)行一個任務。 參考: JavaScript 運行機制詳解:再談Event Loop 深入理解JavaScript的執(zhí)行過程--單線程的JS 細說JavaScript單線程的一些事 The JavaScript Event Loop: Exp...
閱讀 1415·2021-11-25 09:43
閱讀 2274·2021-09-27 13:36
閱讀 1128·2021-09-04 16:40
閱讀 1968·2019-08-30 11:12
閱讀 3325·2019-08-29 14:14
閱讀 579·2019-08-28 17:56
閱讀 1338·2019-08-26 13:50
閱讀 1260·2019-08-26 13:29