如何调试node.js导致100%的CPU使用率?

时间:2012-04-16 00:41:27

标签: debugging node.js express

我有一个使用express和redis的节点应用程序。在我们的开发服务器上,经过一些使用后节点开始使用100%的cpu。应用程序仍然响应,但top报告节点使用100%。在重新启动节点之前,cpu不会丢弃。

我没有把它钉在导致它的任何特定路线或功能上。

诊断此问题的最佳方法是什么?

我用v8-profiler查看了node-inspector,它给了我同样的错误报告 https://github.com/dannycoates/v8-profiler/issues/10

9 个答案:

答案 0 :(得分:18)

您可以使用node-tick配置应用。

  1. node-tick
  2. 安装sudo npm -g install tick
  3. 使用已启用的个人资料node --prof ./app.js
  4. 运行您的应用
  5. 使用CPU 100%使用一段时间后停止使用您的应用
  6. 您可以在app目录中看到v8.log,现在可以使用node-tick-processor
  7. 阅读它
  8. 运行node-tick-processor并解释结果
  9. 将v8.log加载到chrome://跟踪以分析为树。
  10. node js cpu 100%

答案 1 :(得分:16)

我通过编写脚本来记录每个请求然后重放它们来找到问题。

问题是由于我有一个没有返回的回调引起的。

myAsncFunc(function(err, data) {

    if (err) { callback(err) }

    //node kept going after the error was returned to the user.
    // make sure you, return callback(err)

})

这是我对任何感兴趣的人的replay.js代码。

var request = require('request');
var async = require('async');
var redis = require('redis');


var host = 'http://myhost.com';
var jobs = true;

var client = redis.createClient();

async.whilst(
    function () { return jobs; },
    function (callback) {
        client.lpop('history', function(err, url) {
            console.log(url);
            if (!url) {
                jobs = false;
                callback();
            }
            request.get({url:host+url}, function() {
                callback();
            });
        })
    },
    function (err) {
        console.log('done')
    }
);

在你的快递中。

app.get('/*', function(req, res, next) {
    var url = req.originalUrl;
    redis.rpush('history', url);   
    next();
});

这很酷,因为播放的每个历史项目都会再次添加到队列中,因此它会不断循环,每次访问新页面时,它都会将其添加到队列中。

答案 2 :(得分:4)

如果您将UI应用程序与Webpack一起使用,请注意watchOptionswatch。 对我来说,禁用民意测验可以解决问题

watchOptions: {
            poll: false
        }

或者您可以设置一个时间,如poll: 3000一样触发轮询(每3秒一次) https://webpack.js.org/configuration/watch/#watchoptionsignored

答案 3 :(得分:3)

我也经历了100%的CPU使用率,直到我关闭管理员模式(导致节点重新启动,当文件发生变化时)。

这可能不会回答这个问题,但是如果像我这样的新手担心CPU使用情况,可能就是这种情况。

答案 4 :(得分:2)

恒定循环通常以100%CPU恒定运行。在单线程nodejs中,这是一个真正的问题,但是不幸的是缺少有关它的信息。尽管您声明服务器仍然可以响应并且无限循环不是您的情况,但是您仍然可以找到有用的提示来调试实时的nodejs应用程序。

最终,我发现了唯一有用的article: 如何在nodejs中跟踪死循环:

通过SSH连接到服务器。标识nodejs进程ID。 现在,告诉我们侦听调试请求的过程。 是的,我们使用的命令是kill。不,我们不会终止该过程。我们正在向它发送不同的信号。

kill -SIGUSR1 4702

执行此操作后,该过程将打开调试器连接。实际上,它将在控制台日志中打印一个特殊的URL,您可以在Chrome中打开该URL来调试该过程!但是,也许您不想只是为了建立连接而在防火墙和容器配置中钻孔。是的,我也没有。 因此,让我们在命令行进行调试:

node inspect -p 4702

您会看到以下提示:

debug>

然后输入:

pause

然后您回来:

break in file:///somewhere/something.js:555
>555         for (prop in inputObject) {
510             if (hasOwnProp(inputObject, prop)) {
511                 normalizedProp = normalizeUnits(prop);

是的!我们有第一个提示。该应用程序正在执行something.js文件中的第555行。 这可能足以立即看到该错误。但是通常我们需要更多的信息。您可以键入backtrace以获得完整的堆栈跟踪:

#0 someFunctionName file:///somewhere/somefile.js:444:22
#1 someFunctionName file:///somewhere/somefile.js:555:33
#2 someFunctionName file:///somewhere/somefile.js:666:44

...依此类推。

答案 5 :(得分:1)

也许你在某处使用nextTick进行某些计算,这会不断地摧毁CPU。

如果你无法运行配置文件那么很难找出哪个方法是垃圾cpu。还有一件事是使用记录器中间件http://senchalabs.github.com/connect/middleware-logger.html

来检查快速日志

答案 6 :(得分:0)

这可能是因为你是直接的文件数量。例如node_modules文件夹。 你需要使用-i param忽略该文件夹。所以它应该是这样的: supervisor -i ./node_modules app

答案 7 :(得分:0)

如果您使用nodemon来监视文件,请考虑使用文件较少的文件夹的路径。例如让nodemon监视安装有bower或npm的库文件夹会导致CPU使用率很高,原因是其中包含成千上万个文件。

这是我的示例nodemon.json文件:

{
    "watch": ["views","routes"],
    "ext": "html, js"
}

像魅力一样工作。

答案 8 :(得分:0)

另一个选择是我们可以使用Flame Graph并查看函数调用导致cpu高。 命令如下所示

$> git clone https://github.com/brendangregg/FlameGraph.git

$> perf record -F 99 -p 1812 /*process id*/ -g --call-graph dwarf

$> perf script > out.perf

$> FlameGraph/stackcollapse-perf.pl out.perf > out.folded
$> FlameGraph/flamegraph.pl out.folded > out.svg