Node 高性能異步I/O框架

1,什麼是Node?

      首先介紹下什麼是nodejavascript

          1,單線程前端

               node保持了javascript在瀏覽器中單線程的特色,Node中,Javascript與其他線程沒法共享任何狀態。java

               單線程好處:不用到處在乎狀態的同步,沒有死鎖,也沒有線程上下文切換帶來的性能開銷。node

               單線程壞處:沒法利用多核cpu,錯誤會引發整個應用退出,應用的健壯性值得考驗,大量計算佔用CPU沒法繼續調用異步I/O。git

              (注意:針對這些單線程壞處,node都有解決方案,這裏不談)es6

          2,跨平臺 (基於libuv)github

兼容Windows和*nix平臺主要得益於Node在架構層的的改動,它在操做系統與Node與操做系統之間構建了一層平臺層框架,即libuv。目前,libuv已是許多系統實現跨平臺的基礎組件。web

經過良好的架構,Node的第三方C++模塊也能夠藉助libuv實現跨平臺,目前,除了沒有保持更新的C++模塊外,大部分C++模塊都能實現跨平臺的兼容。apache

          3,模塊機制

                Java有類文件,Python有import機制,Ruby有require,PHP有include和require。瀏覽器端Javascript是沒有標準的模塊機制的,只能經過<script>標籤引入代碼顯得雜亂無章,npm

               語言自己沒有組織和約束能力,開發者不得不經過命名空間等方式人爲約束代碼。-》AMD,CMD。

              CommonJS規範:但願javascript可以在任何地方運行。

                 CommonJS的規範提出主要是爲了彌補當前Javascript沒有標準的缺陷,以達到像Python,Ruby和Java具有開發大型應用的基礎能力,而不是停留在小腳本程序的階段.NodeJS是這種規範的實現

                 CommonJS規範涵蓋了模塊,二進制,Buffer,字符集編碼,I/O流,進程環境,文件系統,套接字,單元測試,Web服務網管接口,包管理等。

                  CommonJS有不少實現,其中不乏不少大名鼎鼎的項目,好比 說:Apache的CouchDBnode.js等。但這些項目大 部分只實現了CommonJS的部分規範。具體的項目和實現部分參見官方網站的說                        明:http://commonjs.org/impl/

                   

                    Node模塊實現

 

 

 

 

          4,應用場景

                I/O密集型

               是否不擅長cpu密集型?

      

 

 

 

2, 異步的原理。        

            但凡這種「既是單線程又是異步」的語言有一個共同特色:它們是 event-driven 的。驅動它們的 event 來自一個異構的平臺。

      異步調用(封裝參數)-》線程池(iocp)-》事件循環(監聽者-》執行回調函數)

        阻塞I/O與非阻塞I/O:操做系統內核對於I/O只有兩種方式:阻塞與非阻塞。

               [注]:操做系統對計算機進行了抽象,將全部輸入輸出設備抽象爲文件,內核在進行文件I/O操做時,經過文件描述符進行管理,而文件描述符相似於應用程序與系統內核

       之間的憑證。應用程序若是須要進行I/O調用,須要先打開文件描述符,而後根據文件描述符去實現文件的數據讀寫。此處阻塞/O與非阻塞I/O的區別在於阻塞I/O完成整個獲取

       數據的過程,而非阻塞I/O則不帶數據直接返回,要獲取數據,還須要經過文件描述符再次讀取。

             阻塞I/O的一個特色是必定要等待系統內核層面完成全部數據操做後,調用才結束。以讀取磁盤文件爲例:系統內核在完成磁盤尋道,讀取數據,複製數據到內存中以後這個調

       用才結束。如圖:

                      

            阻塞I/O形成了CPU等待,浪費了等待時間,CPU的處理能力不能獲得充分利用。爲了提升性能,內核提升了非阻塞I/O。非阻塞I/O跟阻塞I/O的區別爲調用以後當即返回,如圖:

           

             非阻塞I/O返回以後,CPU的時間片能夠用來處理其餘事務,此時性能提高是明顯的。

            但非阻塞I/O也存在一些問題。因爲完整的I/O沒有完成,當即返回並非業務層指望的數據,而僅僅是打當前調用的狀態,爲了獲取完整的數據,應用層序須要重複調用I/O操做來

           確認是否完成。這種重複的調用判斷操做是否完成的技術叫作輪詢。[注]:任意技術都並不是是完美的,阻塞I/O形成CPU等待浪費,非阻塞I/O帶來的麻煩倒是須要輪詢取確認是否

          徹底完成數據獲取,他會讓CPU處理狀態判斷,是對CPU的資源浪費。

          輪詢技術是有演進的,以減小I/O狀態判斷的CPU損耗。從read->select->poll->epoll。具體狀況這裏不談。

         理想的非阻塞異步I/O:咱們指望的完美的異步I/O應該是應用程序發起非阻塞調用,無需經過遍歷或者事件喚醒燈方式輪詢,能夠直接處理下一個任務,只須要在I/O完成後經過信號

         或者回調函數講數據傳遞給應用程序便可,以下圖:

                 

        幸運的是,在Linux中存在這中方式,它提供一個異步的I/O方式(AIO)就是經過信號或回調來傳遞數據的。但不幸的是,只有Linux中有,而且AIO只支持內核I/O中的O_DIRECT方法

       讀取,而且沒法利用系統緩存。

      現實的異步I/O

              現實確定比理想要骨感一些,可是要達成異步I/O的目標,也並不是難事。前面咱們講場景都限定在單線程的狀態下,多線程的方式就是另外一番風景了。經過讓部分線程進行阻塞I/O

      或者非阻塞I/O加輪詢技術來完成數據獲取,讓一個線程進行計算,經過線程之間的同窗講I/O獲得數據進行傳遞,這就輕鬆實現了異步I/O(儘管是模擬的)。

           

                  

        [注]:這裏的I/O不只僅只侷限於磁盤讀寫*nix將計算機抽象了一番,磁盤文件,硬件,套接字等幾乎全部計算機資源都被抽象成了文件,所以這裏的描述的阻塞和非阻塞的狀況

         一樣適合套接字等。

         [注]:咱們雖然時常提到Node是單線程的,這裏的單線程僅僅指的是Javascript執行在但造成中罷了。在Node中,不管是什麼平臺,內部完成的I/O任務都是另有線程池的。

 

 3,爲何要用異步?

      

4,經常使用的異步庫

       Deferred是前端解決異步操做的一種編程範式,後來出現的Promise規範更是讓其普適性大大提升。不過Promise規範也存在分岐。如今最流行的是Promise/A+規範。

 4,1  Promise

      在這些Promise的實現類庫中,主要對兩種類型的類庫進行介紹。一種是被稱爲 Polyfill 的類庫,另外一種是即具備  Promises/A+兼容性 ,又增長了本身獨特功能的類庫。

  

  PolyFill

       只須要在瀏覽器中加載Polyfill類庫,就能使用IE10等或者尚未提供對Promise支持的瀏覽器中使用Promise裏規定的方法。也就是說若是加載了Polyfill類庫,就能在還不支持Promise          的環境中,運行Promise。

     1,jakearchibald/es6-promise

       一個兼容 ES6 Promises 的Polyfill類庫。 它基於 RSVP.js 這個兼容 Promises/A+ 的類庫, 它只是 RSVP.js 的一個子集,只實現了Promises 規定的 API。

     2,yahoo/ypromise

      這是一個獨立版本的 YUI 的 Promise Polyfill,具備和 ES6 Promises 的兼容性。 

    3,getify/native-promise-only

       以做爲ES6 Promises的polyfill爲目的的類庫 它嚴格按照ES6 Promises的規範設計,沒有添加在規範中沒有定義的功能。 若是運行環境有原生的Promise支持的話,則優先使用原生的          Promise支持。一個兼容 ES6 Promises 的Polyfill類庫。 它基於  RSVP.js 這個兼容 Promises/A+ 的類庫, 它只是 RSVP.js 的一個子集,只實現了Promises 規定的 API。 
 

  Promise擴展類庫

       1,kriskowal/q

       使用過Node.js的人可能會知道Q模塊,Q實現了Promises和 Deferreds等規範,在Node.js中環境或瀏覽器環境中使用。

      2,then/promise

       一個Promise/A+簡單實現模塊,除實現then方法外,還擴展一些標準外的方法,在Node.js中環境或瀏覽器環境中使用。

      3,petkaantonov/bluebird

    bluebird類庫除了兼容Promise規範以外,還對Promise對象進行了必定的擴展,如:取消promise對象的運行等。另外,還在運行效率上進行了必定的優化。bluebird也是一             個npm模塊,能夠在Node.js中環境或瀏覽器環境中使用。 

 

    其餘
      Async.js是一個流程控制工具包,提供了直接而強大的異步功能。參考這裏: http://blog.fens.me/nodejs-async/
 《深刻淺出node》做者樸靈寫的EventProxy參考: https://github.com/JacksonTian/eventproxy   
    大名鼎鼎的 co正是TJ大神基於ES6的一些新特性開發的異步流程控制庫,基於它所開發的 koa更是被視爲將來主流的web框架。

   Wind.js   https://github.com/JeffreyZhao/wind   http://blog.fens.me/nodejs-async-windjs/

相關文章
相關標籤/搜索