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!
编程