到底是用 Ajax 还是 Socket.IO? 用测试数据说话!
本文译自 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等)。 -
Ajax 通常比 Socket.IO快 … -
Socket.IO 可以进行双向通信,其中客户端或服务器端都可以发起请求。在 AJAX 中,只有客户才能发起请求。
现在对于我自己的程序,最感兴趣的是发起请求并从(Node.js)服务器获取数据的速度!
所以我决定对 Ajax 和 socket 速度进行测试,看看哪一个更快(至少在我的硬件和软件环境下)!我的硬件环境是:i5 处理器,8GB 内存和英特尔 X25 SSD 硬盘。
严格来说,任何性能测试都取决于你的硬件和软件配置,一定要在你自己的环境中去测试,不要过于依赖你在互联网上找到的各种信息,因为还有更多的问题需要你自己去发现。
我要做的测试需要满足以下要求:
-
测试: -
Ajax -
Socket.IO 持续连接模式 -
Socket.IO 非持续链接模式 -
测试客户端与服务器之间进行 10、100,、250、500 条数据交换时的情况 -
中间件服务器(Node.js Web 服务器)和客户端(浏览器)之间交换的每条数据都是一个 4KBytes 的随机数据串 -
在 release(非调试)模式下运行服务器 -
用 Firefox 作为客户端 -
最小化控制台消息输出,不管是服务器端还是客户端 -
在客户端页面硬性重新加载后进行每个测试 -
每次测试至少重复 3 次,以确保结果一致
测试 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 |
我们从测试结果结果中注意到:
-
每种类型的测试,其结果遵循线性增长的规律,表明结果是一致的。 -
结果清楚地表明,当使用 Socket.IO 非持久性连接时,性能数字比其他数据差得多。 -
在 AJAX 和 Socket.IO 持久连接之间似乎并没有太大区别——仅仅是几毫秒的差异。这意味着,如果你每天的数据交换次数不超过 10,000 次的话,用户基本上不会注意到速度差异。
下图描述了在测试中获得的数字:
那么接下该做什么?
我必须弄清楚自己需要支持什么样的数据流量,然后重新运行这些测试,但这次不包括 Socket.IO 非持久连接。因为很明显,我需要在 AJAX 和持久的 Socket.IO 连接之间进行选择。
实际在“小流量”的网站上,它们的速度差异并不会像我们所想象的那样大,所以我在确定自己的解决方案时,还需要研究每种技术的其他方面的优缺点!
这里有一些资源,可以找到关于Node.js、Socket.IO 和 AJAX 的一些有趣的东西:
-
http://socket.io/#how-to-use -
http://www.hacksparrow.com/jquery-with-node-js.html -
http://www.slideshare.net/toddeichel/nodejs-talk-at-jquery-pittsburgh -
http://tech.burningbird.net/article/node-references-and-resources -
http://davidwalsh.name/websocket
译者推荐
开发中的技术选型并不是随意确定的,想要知道更多技术特点和适用场景,但是却听够了毫无深度的前端“水”课?我也是一位前端工程师,深知程序员的时间有多宝贵,所以我不会拿毫无营养的“水”课,来浪费大家的时间。我的前端全栈精英班打磨了3年时间,培育了1000+名前端精英,课程的目标就是带大家冲年薪40万。
课程涵盖大前端的全部领域,并对传统的Web前端全栈深入教学。如利用前端知识开发 AI、VR、AR、iOS、Android、PC、Server、智能硬件。同时我们将核心打造JavaScript语言新发展、Vue源码分析、前端持续集成方案、MV*框架深度分析 、前端图形学、NodeJS大规模站点架构等。兼具深度和广度,带你成为真全栈!
如果你对这门课程产生了点兴趣,扫描下方二维码,即可免费报名试学
免费赠送 Webpack 全系列教程
报名试学的童鞋,我们还将免费赠送 Webpack 全系列课程,从0到1再到10,攻克Webpack!
课程大纲:
-
使用webpack快速构建SPA应用 -
使用webpack快速构建多页应用 -
webpack在一线开发中的优化 -
webpack核心源码分析原理课 -
手把手带你从头实现webpack -
Webpack开发SPA与MPA核心知识 -
基于AST实现简版Webpack -
Webpack5新特性尝鲜与微前端