Node.JS

十个Node.js开发易犯错误之二:堵塞事件循环

上页

 因为Node.js运行在一个单线程内,任何堵塞住事件循环的代码将会导致整个应用系统堵塞停顿,这意味着如果你的Web服务器有 几千连接,碰巧你堵塞了事件循环,那么这些客户端只能永远在等待响应。

 这里是一些如何可能会导致堵塞的场景:

  • Parsing a big json payload 使用 JSON.parse函数分析一个很大的JSON;
  • 试图在后端对大文件中内容实现语法高亮显示,使用一些 Ace or highlight.js);
  • 一次性解析一个大的输出,比如从child process 实现git日志输出命令。.

 这些事情也许是在无意中进行,因为解析一个15M的输出并不经常发生,但是这足够让黑客抓住了你的弱点。

 很幸运你能监视事件循环的延迟以便发现异常,这个能通过商业产品如 StrongOps或开源模块如 blocked解决。

 这些产品后面的思想是 精确跟踪间隔时间accurately track the time并报告,每次间隔的时间差用来作为比较,下面是它们如何实现的细节:

  • 获得当前时间和传送参数时间之间的细粒度的时间差;
  • 以平常间隔时间判断当前时间循环的延时时间。
  • 如果延时超过一个门槛,以绿色或红色显示延时
  • 为了看到其运行,需要执行300毫秒的重量计算

 

var chalk = require('chalk');

 

var getHrDiffTime = function(time) {

  // ts = [seconds, nanoseconds]

  var ts = process.hrtime(time);

  // convert seconds to miliseconds and nanoseconds to miliseconds as well

  return (ts[0] * 1000) + (ts[1] / 1000000);

};

 

var outputDelay = function(interval, maxDelay) {

  maxDelay = maxDelay || 100;

 

  var before = process.hrtime();

 

  setTimeout(function() {

    var delay = getHrDiffTime(before) - interval;

 

    if (delay < maxDelay) {

      console.log('delay is %s', chalk.green(delay));

    } else {

      console.log('delay is %s', chalk.red(delay));

    }

 

    // repeat

    outputDelay(interval, maxDelay);

  }, interval);

};

 

outputDelay(300);

 

setInterval(function compute() {

  var sum = 0;

 

  for (var i = 0; i <= 999999999; i++) {

    sum += i * 2 - (i + 1);

  }

}, 2000);

 

在运行之前需要安装 chalk ,运行上述代码以后,你会看到如下显示:

参考更多该功能的开源项目:

 如果你使用该技术,你就能准确分析你的代码中哪里会导致堵塞延时了。

 

本节源码下载:Github

下页