本文译自 A Node.js speed dilemma: AJAX or Socket.IO?。
当我开始写自己的第一个 Node.js 项目时,发现处理浏览器(客户端)和中间件之间的通信是不可避免的。
我已经非常熟悉 Ajax 了,但是在学习 Node.js 时,我发现了 Socket.IO 模块,甚至在互联网上发现了一些非常不错的代码案例,非常好用。
所以这很快成为一个难题:
应该选哪个,Ajax 还是 sockets.io?
显然,由于我的经验非常有限,所以我需要更多的信息。换句话说应该好好的 Google 一番。
显然相关的信息非常多,但是需要过滤掉那些没用的 "噪音",才能得到真正有用的内容。先和大家分享一些相关的链接:
-
http://stackoverflow.com/questions/7193033/nodejs-ajax-vs-socket-io-pros-and-cons
-
http://podefr.tumblr.com/post/22553968711/an-innovative-way-to-replace-ajax-and-jsonp-using
-
http://stackoverflow.com/questions/4848642/what-is-the-disadvantage-of-using-websocket-socket-io-where-ajax-will-do?rq=1
-
http://howtonode.org/websockets-socketio
总而言之,以下是我发现的东西:
-
Socket.IO 在客户端和服务器间的用的是持续连接,所以很容易就会达到服务器端所允许的并发连接数的上限,而相同的资源可以支持更多的 Ajax 异步请求。
-
使用AJAX,你可以请求 RESTful 接口。这意味着你可以利用现有的 HTTP 服务,例如:代理
缓存
请求和带条件的GET请求。
-
与 Socket.IO 相比,Ajax 的开销更大(例如:HTTP头,Cookie等)。
-
-
Socket.IO 可以进行双向通信,其中客户端或服务器端都可以发起请求。在 AJAX 中,只有客户才能发起请求。
现在对于我自己的程序,最感兴趣的是
发起请求并从(Node.js)服务器获取数据的速度!
所以我决定对 Ajax 和 socket 速度进行测试,看看哪一个更快(至少在我的硬件和软件环境下)!我的硬件环境是:i5 处理器,8GB 内存和英特尔 X25 SSD 硬盘。
严格来说,任何性能测试都取决于你的硬件和软件配置,一定要在你自己的环境中去测试,不要过于依赖你在互联网上找到的各种信息,因为还有更多的问题需要你自己去发现。
我要做的测试需要满足以下要求:
-
-
测试客户端与服务器之间进行 10、100,、250、500 条数据交换时的情况
-
中间件服务器(Node.js Web 服务器)和客户端(浏览器)之间交换的每条数据都是一个 4KBytes 的随机数据串
-
-
-
-
-
测试 Socket.IO,使用持久连接
我写了一小型的 小Node.js 服务器,用来处理客户端请求:
io.sockets.on('connection', function (client) {
client.on('send_me_data', function (idx) {
client.emit('you_have_data', idx, random_string(4096));
});
});
这是我用于测试的 JS 客户端脚本:
var socket = io.connect(document.location.href);
socket.on('you_have_data', function (idx, data) {
var end_time = new Date();
total_time += end_time - start_time;
logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
if (idx++ < countMax) {
setTimeout(function () {
start_time = new Date();
socket.emit('send_me_data', idx);
}, 500);
}
});
测试 Socket.IO,使用非持久连接
这次测试中的每次数据交换,我都打开一个新的 socket-io 连接。
Node.js 服务器代码与上一个类似,但是我决定在连接之后立即发送客户端数据,因为每次数据交换都会启动一个新的连接:
io.sockets.on('connection', function (client) {
client.emit('you_have_data', random_string(4096));
});
客户端测试代码:
function exchange(idx) {
var start_time = new Date();
var socket = io.connect(document.location.href, {'force new connection' : true});
socket.on('you_have_data', function (data) {
var end_time = new Date();
total_time += end_time - start_time;
socket.removeAllListeners();
socket.disconnect();
logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
if (idx++ < countMax) {
setTimeout(function () {
exchange(idx);
}, 500);
}
});
}
测试 Ajax
最后是 Ajax 测试。
Node.js 服务器代码与以前的代码不同:
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end('_testcb(\'{"message": "' + random_string(4096) + '"}\')');
至于客户端代码,这是我以前测试的:
function exchange(idx) {
var start_time = new Date();
$.ajax({
url : 'http://localhost:8080/',
dataType : "jsonp",
jsonpCallback : "_testcb",
timeout : 300,
success : function (data) {
var end_time = new Date();
total_time += end_time - start_time;
logMsg(total_time + '(ms.) [' + idx + '] - Received ' + data.length + ' bytes.');
if (idx++ < countMax) {
setTimeout(function () {
exchange(idx);
}, 500);
}
},
error : function (jqXHR, textStatus, errorThrown) {
alert('Error: ' + textStatus + " " + errorThrown);
}
});
}
需要注意的是在 Node.js 中使用 Ajax 时,需要考虑到可能的跨域请求和同源策略问题,所以应该用基于 JSONP 的格式。
测试结果的数据
我分别运行了 10、100、250 和 500 个数据交换的测试,这是最终测试结果:
Data exchanges
|
Socket.IO非持续连接 (ms.)
|
AJAX (ms.)
|
Socket.IO 持续连接 (ms.)
|
10
|
90
|
40
|
32
|
100
|
900
|
320
|
340
|
250
|
2,400
|
800
|
830
|
500
|
4,900
|
1,500
|
1,600
|
我们从测试结果结果中注意到: