在网页编程领域,我一直使用ASP.NET或LAMP技术写代码,这成为我生活的绝大部分内容。现在,新的亮点是node.js。它是一个在服务器端运行javascript的框架,并据说通过使用异步I/ O,提升了一些性能。
该理论认为,同步I/O 阻塞模型的工作原理是这样的:
(注* 关于异步非阻塞模型的工作原理,可参见: 是什么让Node.js比Java更快? )
I / O是一个典型的网络事务(web transaction)中的最昂贵的部分。当一个请求到达Apache Web服务器,它传递给PHP解释器来执行脚本的动态内容。现在到了棘手的部分 - 如果PHP脚本想要从磁盘/数据库读取或存取数据,这就成了最慢的一环。当你调用PHP函数 file_get_contents(),整个线程被阻塞,直到内容获取完成!直到你的脚本获得文件内容,服务器不能做任何事情。想像一下当并发请求增加数倍时,会发生什么?他们要排队,因为没有可用的线程可以做这份工作,因为他们都被I/O阻塞了!
这里谈到了 node.js 中独特的卖点缘于 node.js 在几乎所有的功能中都使用异步I / O,在上述方案中,只要服务器线程一被释放,文件检索功能(fs.readFile)就被调用。然后,一旦在I / O完成后,节点才会执行传进来的回调函数(早些时候通过fs.readFile)。在此期间,该有价值的线程就可以用于服务其它一些请求。
所以,这就是关于它的理论。但我不是那种只是因为它被大肆宣传或者每个人都使用它就接受新风潮的人。不,我想在知道事实真相,并亲自来验证它。我想看看这个理论是否能经得起实际操作的考验。
所以为了测试它,我自己写了两个简单的脚本 —— 一个在PHP(托管在apache2的),另一个是JavaScript(托管在node.js上的)。测试本身是非常简单的。该脚本将:
1,接受请求。
2,生成一个随机的108千字节的字符串。
3,将字符串写到磁盘的文件上。
4,从磁盘中读取内容。
5,在返回的响应流中返回字符串。
这是第一个脚本,index.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;
这是第二个脚本
//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 athttp://127.0.0.1:8124/')
;
然后,然后我通过apache评测工具,向他们两者一共发了2000个请求(200并发)。当我看到时间统计结果,我大吃一惊:
#PHP: Concurrency Level: 200 Time taken for tests: 574.796 seconds Complete requests: 2000 #node.js: Concurrency Level: 200 Time taken for tests: 41.887 seconds Complete requests: 2000
真相大白了。node.js比PHP快14倍!这结果是惊人的。它简直意味着node.js将在不久的未来成为编写性能驱动应用程序事实上的标准,这也是毫无疑问的!
大家一致认为NodeJS生态系统还没有被广泛开发掘,并且大多数节点模块,比如数据库连接,网络接入,公用设施等,正在积极开发中。但尽管如此,看到这些结果后,实在是太显而易见了。在发展node.js应用程序所花费的任何额外的努力都是非常值得的。 PHP的可能仍然保持着“网页之王”的状态,但是作为焦点的node.js,我估计这种状态不会持续很长时间!
更新
从下面一节看了一些评论之后,我觉得有义务也创建一个C#/mono 版本。不幸的是,这个已经被证明是最慢的一组(约40秒1个请求)。也许是我的程序写错了,或者我的代码有什么错误。一旦等我闲下来我就会解决它,也许我的下一篇文章就是ASP.NET vs node.js vs PHP!。
参考文献:
1 https://en.wikipedia.org/wiki/Node.js
2 http://notes.ericjiang.com/posts/751
4.https://code.google.com/p/node-js-vs-apache-php-benchmark/wiki/Tests
也来做网站吗?