【譯】node js event loop part 1.1

原文node

先說1.1總攬:react

  • Reactor模式
  • Reactor模式中的協調機制Event Loop
  • Reactor模式中的事件分離器Event Demultiplexer
  • 一些Event Demultiplexer處理不了的複雜I/O接口好比File I/O、DNS等
  • 複雜I/O的解決方案
  • 未完待續

前言

nodejs和其餘編程平臺的區別在於如何去處理I/O接口,咱們聽一我的介紹nodejs,老是會說是一個基於v8引擎,沒有堵塞,事件驅動的語言,那這些又意味着什麼呢?什麼叫‘沒有堵塞’和‘事件驅動’?全部的答案都在nodejs的核心——Event Loop
在這一系列的帖子中,咱們將一塊兒去描述什麼是Event Loop,它是如何工做的,它是如何影響咱們的應用的,如何充分的利用他甚至更多。爲何不用一篇代替一個系列的帖子呢,由於這樣的話,他就會變成一個很長很長的帖子,我會確定會錯過不少東西,所以我才把它寫成一個系列,在第一篇帖子中,我將講述nodejs如何工做,如何經過I/O,他如何與其餘平臺一塊兒工做等。linux

Reactor Pattern

nodejs工做在一個事件驅動的模型中,這個模型涉及一個事件分離器和事件循環,全部的I/O請求最終將會生成一個事件完成、事件失敗或者喚醒其餘事件的結果。這些事件將會根據如下規則作處理:編程

  • 1.事件分離器收到I/O請求,以後將這些請求委託給相應的硬件
  • 2.曾經被處理過的請求(好比來自可讀取文件的數據,來自可讀取接口的數據),事件分離器會爲要進行的特殊操做添加註冊回調程序。
  • 3.若是事件能夠在事件循環中被處理,那麼將有序的被執行,直到循環爲空
  • 4.若是沒有事件在事件循環中,或者事件分離器沒有添加任何請求,這個 程序將被完成,不然,程序將從第一步在開始,進行循環操做。

這整個工程的協調機制咱們叫作Event Loop設計模式

Event Loop

Event Loop實際上是一個單線程的半無限循環,爲何會說是半無限呢?由於在沒有工做須要完成的時候程序會退出。從開發者的角度來講,這些是程序退出的點。網絡

注意:不要把Event Loop和Event Emitter弄混淆,Event Emitter和這個機制徹底是不一樣的概念,在最後一篇帖子,我會解釋Event Emitter是如何經過Event Loop影響事件的處理。

上面的圖是對NodeJs如何工做以及展現一種被叫作Reactor Pattern的主要組件的設計模式的高級概覽。
可是真正的複雜度遠超於它,那它有多複雜呢?異步

Event demultiplexer不是一個在全部os平臺中解析全部I/O類型的單一組件。
Event queue在這裏展現出來的不是一個單一的隊列,在其中全部類型的事件會在隊列中排隊或者從隊列中移除,而且I/O不是惟一一個要排隊的事件類型

讓咱們繼續深挖async

Event Demultiplexer

Event Demultiplexer並非一個現實存在的組件,而是在reactor pattern中的一個抽象概念。ide

在現實中,Event Demultiplexer 在不一樣的系統中以不一樣的名字被實現,好比在linux中叫作epoll, 在MacOS中叫作kqueue,在Solaris中叫event post,在window系統下叫作IOCP等。函數

nodeJS可使用Event Demultiplexer提供的底層非阻塞、異步硬件I/O功能。

Complexities in File I/O

可是使人苦惱的是,不是全部類型的I/O均可以使用Event Demultiplexer被執行,甚至是在相同的操做系統中,支持不一樣類型的I/O也是很複雜的。

一般來講,epoll, kqueue, event ports和IOCP可使用非阻塞的方式執行網絡I/O。

可是文件I/O就複雜多了,某些系統,好比Linux不支持徹底異步的方式去訪問文件系統,在MacOS系統中文件系統對事件的發送和接收會有限制(你能夠在這裏瞭解更多)。

爲了提供徹底異步而去解決全部文件系統的複雜性是很是複雜的,幾乎是不可能的。

Complexities in DNS

和文件I/O同樣,由node API提供某些DNS的功能也存在必定的複雜性。

好比dns.lookup等Node DNS功能訪問系統的一些配置文件,例如nsswitch.conf、resolv.conf和/etc/hosts。

上面描述的文件系統複雜性也適用於dns.resolve函數。

The solution?

所以,引入了一個線程池來支持I/O功能,這些功能不能由硬件異步I/O實用程序(如epoll / kqueue / event ports或IOCP)直接解決。

如今咱們知道不是全部的I/O功能均可以在線程池中運行。nodeJS已經盡最大努力來使用非阻塞和硬件的異步I/O方式來完成大部分I/O功能,可是對於一些複雜的、阻塞的I/O仍是經過引入一個線程池的方式來解決

未完待續

該篇先翻譯到這,有些地方翻譯的很差請指出,過幾天我會繼續出第二篇。

相關文章
相關標籤/搜索