vlambda博客
学习文章列表

到底是用 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

总而言之,以下是我发现的东西:

  1. Socket.IO 在客户端和服务器间的用的是持续连接,所以很容易就会达到服务器端所允许的并发连接数的上限,而相同的资源可以支持更多的 Ajax 异步请求。
  2. 使用AJAX,你可以请求 RESTful 接口。这意味着你可以利用现有的 HTTP 服务,例如:代理 缓存请求和带条件的GET请求。
  3. 与 Socket.IO 相比,Ajax 的开销更大(例如:HTTP头,Cookie等)。
  4. Ajax 通常比 Socket.IO快 …
  5. 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

我们从测试结果结果中注意到:

  1. 每种类型的测试,其结果遵循线性增长的规律,表明结果是一致的。
  2. 结果清楚地表明,当使用 Socket.IO 非持久性连接时,性能数字比其他数据差得多。
  3. 在 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!

课程大纲:

  1. 使用webpack快速构建SPA应用
  2. 使用webpack快速构建多页应用
  3. webpack在一线开发中的优化
  4. webpack核心源码分析原理课
  5. 手把手带你从头实现webpack
  6. Webpack开发SPA与MPA核心知识
  7. 基于AST实现简版Webpack
  8. Webpack5新特性尝鲜与微前端

扫码申请试学