在網(wǎng)頁編程領(lǐng)域,我一直使用ASP.NET或LAMP技術(shù)寫代碼,這成為我生活的絕大部分內(nèi)容?,F(xiàn)在,新的亮點(diǎn)是node.js。它是一個在服務(wù)器端運(yùn)行javascript的框架,并據(jù)說通過使用異步I/ O,提升了一些性能。
該理論認(rèn)為,同步I/O 阻塞模型的工作原理是這樣的:
(注* 關(guān)于異步非阻塞模型的工作原理,可參見: 是什么讓Node.js比Java更快? )
I / O是一個典型的網(wǎng)絡(luò)事務(wù)(web transaction)中的最昂貴的部分。當(dāng)一個請求到達(dá)Apache Web服務(wù)器,它傳遞給PHP解釋器來執(zhí)行腳本的動態(tài)內(nèi)容。現(xiàn)在到了棘手的部分 - 如果PHP腳本想要從磁盤/數(shù)據(jù)庫讀取或存取數(shù)據(jù),這就成了最慢的一環(huán)。當(dāng)你調(diào)用PHP函數(shù) file_get_contents(),整個線程被阻塞,直到內(nèi)容獲取完成!直到你的腳本獲得文件內(nèi)容,服務(wù)器不能做任何事情。想像一下當(dāng)并發(fā)請求增加數(shù)倍時,會發(fā)生什么?他們要排隊,因?yàn)闆]有可用的線程可以做這份工作,因?yàn)樗麄兌急籌/O阻塞了!
這里談到了 node.js 中獨(dú)特的賣點(diǎn)緣于 node.js 在幾乎所有的功能中都使用異步I / O,在上述方案中,只要服務(wù)器線程一被釋放,文件檢索功能(fs.readFile)就被調(diào)用。然后,一旦在I / O完成后,節(jié)點(diǎn)才會執(zhí)行傳進(jìn)來的回調(diào)函數(shù)(早些時候通過fs.readFile)。在此期間,該有價值的線程就可以用于服務(wù)其它一些請求。
所以,這就是關(guān)于它的理論。但我不是那種只是因?yàn)樗淮笏列麄骰蛘呙總€人都使用它就接受新風(fēng)潮的人。不,我想在知道事實(shí)真相,并親自來驗(yàn)證它。我想看看這個理論是否能經(jīng)得起實(shí)際操作的考驗(yàn)。
所以為了測試它,我自己寫了兩個簡單的腳本 —— 一個在PHP(托管在apache2的),另一個是JavaScript(托管在node.js上的)。測試本身是非常簡單的。該腳本將:
1,接受請求。
2,生成一個隨機(jī)的108千字節(jié)的字符串。
3,將字符串寫到磁盤的文件上。
4,從磁盤中讀取內(nèi)容。
5,在返回的響應(yīng)流中返回字符串。
這是第一個腳本,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 at http://127.0.0.1:8124/');
然后,然后我通過apache評測工具,向他們兩者一共發(fā)了2000個請求(200并發(fā))。當(dāng)我看到時間統(tǒng)計結(jié)果,我大吃一驚:
#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倍!這結(jié)果是驚人的。它簡直意味著node.js將在不久的未來成為編寫性能驅(qū)動應(yīng)用程序事實(shí)上的標(biāo)準(zhǔn),這也是毫無疑問的!
大家一致認(rèn)為NodeJS生態(tài)系統(tǒng)還沒有被廣泛開發(fā)掘,并且大多數(shù)節(jié)點(diǎn)模塊,比如數(shù)據(jù)庫連接,網(wǎng)絡(luò)接入,公用設(shè)施等,正在積極開發(fā)中。但盡管如此,看到這些結(jié)果后,實(shí)在是太顯而易見了。在發(fā)展node.js應(yīng)用程序所花費(fèi)的任何額外的努力都是非常值得的。 PHP的可能仍然保持著“網(wǎng)頁之王”的狀態(tài),但是作為焦點(diǎn)的node.js,我估計這種狀態(tài)不會持續(xù)很長時間!
更新
從下面一節(jié)看了一些評論之后,我覺得有義務(wù)也創(chuàng)建一個C#/mono 版本。不幸的是,這個已經(jīng)被證明是最慢的一組(約40秒1個請求)。也許是我的程序?qū)戝e了,或者我的代碼有什么錯誤。一旦等我閑下來我就會解決它,也許我的下一篇文章就是ASP.NET vs node.js vs PHP!。
參考文獻(xiàn):
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
哈爾濱品用軟件有限公司致力于為哈爾濱的中小企業(yè)制作大氣、美觀的優(yōu)秀網(wǎng)站,并且能夠搭建符合百度排名規(guī)范的網(wǎng)站基底,使您的網(wǎng)站無需額外費(fèi)用,即可穩(wěn)步提升排名至首頁。歡迎體驗(yàn)最佳的哈爾濱網(wǎng)站建設(shè)。
