Node.js到底強在哪裏?

PHP VS NODE.JS: THE REAL STATISTICS一文用PHP和Node.js實現文件讀寫的案例展現二者性能對比, 二者相差14倍之多。究其緣由仍是Node.JS的異步IO。

I/O是Web應用典型的消耗瓶頸,當一個請求達到Apache web服務器時,它將動態腳本內容傳遞到PHP解釋器 ,若是PHP腳本這時向磁盤或數據庫讀寫數據,由於磁盤和數據庫比較慢,就會形成整個請求鏈條的最慢一個環節。當你調用 PHP 函數 file_get_contents(), 整個線程就堵塞住了,直至等到從磁盤或數據庫讀寫數據成功。在這段時間,服務器不能作任何事情。

若是這時還有其餘用戶同時發出請求,對不起,這些用戶請求必須等待了,由於已經沒有線程來處理這些用戶請求,線程都堵塞在I/O了。

( Node.js的異步機制並非強在Http服務器 IO內部機制上,並不如同NIO非堵塞IO那種機制,它的異步強在協調多個堵塞源)

node.js惟一賣點在這裏,它能對全部IO實現異步,一旦文件得到(fs.readFile),服務器線程就空閒被其餘函數調用,一旦整個I/O讀寫所有完成了,node會在讀寫完成後再調用一個回調函數 (這是以前經過fs.readFile一塊兒傳遞過來的)進行後續相關掃尾工做。

下面兩個腳本分別是測試腳本,功能是:
1. 接受一個請求
2. 產生一個隨機數
3. 將隨機數寫入到磁盤文件
4. 再從磁盤文件讀取
5. 返回讀取內容給響應。
php

<?php
//index.php
$s=""; //generate a random string of 108KB and a random filename
$fname = chr(rand(0,57)+65).chr(rand(0,57)+65).chr(rand(0,57)+65).chr(rand(0,57)+65).'.txt';
for($i=0;$i<108000;$i++)
{
    $n=rand(0,57)+65;
    $s = $s.chr($n);
}
 
//write s to a file
file_put_contents($fname,$s);
$result = file_get_contents($fname);
echo $result;
?>

下面是Node.js的代碼:node

//server.js
var http = require('http');
var server = http.createServer(handler);

function handler(request, response) {
//console.log('request received!');
response.writeHead(200, {'Content-Type': 'text/plain'});

s=
""; //generate a random string of 108KB and a random filename
fname = String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) +
String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) +
String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) +
String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) +
".txt";

for(i=0;i<108000;i++)
{
n=Math.floor(65 + (Math.random()*(122-65)) );
s+=String.fromCharCode(n);
}

//write s to a file
var fs = require('fs');
fs.writeFile(fname, s, function(err, fd) {
if (err) throw err;
//console.log("The file was saved!");
//read back from the file
fs.readFile(fname, function (err, data) {
if (err) throw err;
result = data;
response.end(result);
});
}
);
}

server.listen(8124);
console.log('Server running at http:
//127.0.0.1:8124/');

測試結果:web

#PHP:
Concurrency Level:      200
Time taken  tests:   574.796 seconds
Complete requests:      2000
 
#node.js:
Concurrency Level:      200
Time taken  tests:   41.887 seconds
Complete requests:      2000

咱們都知道Node.JS一直很火也很強,其實不多人明白Node.JS到底強在哪裏?

Node.JS在涉及堵塞源讀寫方面要比PHP快十多倍,從某種程度看,Node.JS與PHP相比有點不是一個級別,Javascript和PHP相比可能更合適,Node.JS是一個Web框架,其比PHP在涉及堵塞讀寫上要快,並非Javascript語言比PHP快,而是Node.js處理堵塞源的方式比較高明。

因此,這不是簡單語言細節之爭,而是語言框架之爭。將Node.JS這種異步機制從Javasctipt搬移到其餘語言PHP .NET Java其實都會取得比原來堵塞方式有數十倍提升。

一般過去咱們提高性能的思路是着重細節,好比Java提供Socket和文件等堵塞的NIO,那麼是否是使用Java作一個Web應用,其性能確定賽過Node.JS呢?未必。

再進一步,Java等提供線程的併發能力很強,而Node.JS只是單線程,涉及堵塞源的讀寫時,咱們使用多線程併發編程是否在性能上就能賽過Node.JS呢?也未必,這實際上是將併發能力用錯了地方,堵塞源的讀寫自己是一種序列的串行操做。

Node.js強項不是在內部細節,而是在其高度,以及貼近Web應用這有的場景。Node.JS是一個平衡各個堵塞源的框架,而不是具體解決某個堵塞源的框架。

我曾經用紅綠燈打比喻,一條大路上有多個紅綠燈,如何保證這條大路上的車輛能更暢統統行呢?Node.JS的解決辦法就是設法在車輛靠近每一個紅綠燈時都依次變成綠燈。而NIO或併發編程等解決辦法則只是側重紅綠燈自己的改造提高。紅綠燈路口相似各個堵塞源,好比Http Socket端口讀寫, 文件磁盤讀寫,數據庫讀寫等等,咱們不少時候側重這些堵塞源內部性能微調,直至研究Linux的TCP協議,這是一種向內部向底層挖掘的思惟方式。

Node.JS這種宏觀異步事件處理機制,其核心是至關於一個事件隊列,說白一點,至關於RabbitMQ這些消息系統或BUS等消息總線,咱們已經體會過在大型分佈式系統中消息中間件如何調度多個服務器之間的效率,同理,Node.JS將這種調度機制搬移到一臺服務器內部,將服務器的Socket 文件讀寫等當作是一個堵塞式的獨立服務器。

Node.JS的威力是其異步機制和事件驅動的架構設計魅力,如今流行的Reactive編程是將這種設計進行了推廣。數據庫

來自Node.JS是皇帝新裝一文對Node.JS產生的誤解進行了分析,幾個誤解以下:

1.Node.js 是快的。
這分兩點:
(1)在V8上運行JS很快?
JS其實比Java慢1到5倍,做者認爲Java, Go, Erlang (HiPE), Clojure, C#, F#, Haskell (GHC), OCaml, Lisp (SBCL)等都很快,可是都不具生產性unproductive,沒有一個適合編寫Web服務器。

(2)Node.js是非堵塞,是併發的,基於事件的。
其實Node.JS是單線程,無關乎多線程併發,也不是惟一的能高效處理鏈接的框架,Vert.x, Erlang, Stackless Python, GHC, Go等也很強。

可是人們使用Node.JS可以以簡單投籃的方式讓他們網站提升不少性能。

做者最後認爲,若是你來自一個過分設計的系統(意思指Spring等),作任何事情須要一個AbstractFactoryFactorySingletonBean時,而Node.JS正是由於其結構的缺少讓人耳目一新。

Node.JS讓人們喜歡是由於其產品性productive,也就是開發的高效率,開發生產力很高:I’m so productive with Node.js! Agile! Fast! MVP!
編程

相關文章
相關標籤/搜索