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 ,运行上述代码以后,你会看到如下显示:
参考更多该功能的开源项目:
- https://github.com/hapijs/heavy/blob/bbc98a5d7c4bddaab94d442210ca694c7cd75bde/lib/index.js#L70
- https://github.com/tj/node-blocked/blob/master/index.js#L2-L14
如果你使用该技术,你就能准确分析你的代码中哪里会导致堵塞延时了。
本节源码下载:Github