我有一个使用express和redis的节点应用程序。在我们的开发服务器上,经过一些使用后节点开始使用100%的cpu。应用程序仍然响应,但top报告节点使用100%。在重新启动节点之前,cpu不会丢弃。
我没有把它钉在导致它的任何特定路线或功能上。
诊断此问题的最佳方法是什么?
我用v8-profiler查看了node-inspector,它给了我同样的错误报告 https://github.com/dannycoates/v8-profiler/issues/10
答案 0 :(得分:18)
您可以使用node-tick配置应用。
node-tick
sudo npm -g install tick
node --prof ./app.js
node-tick-processor
并解释结果答案 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一起使用,请注意watchOptions
或watch
。
对我来说,禁用民意测验可以解决问题
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