调试Node.js& Express App - 间歇性地使用100%CPU

时间:2014-08-11 09:33:51

标签: node.js express nginx firebase

我正在使用NGinx + Node.js + Express + Firebase开发应用程序,只需从移动应用程序获取输入并将其存储到Firebase,可选择将文件上传到S3。

用最简单的术语来说,“创建”功能可以做到这一点

  • 验证输入
  • 格式化输入检查是否上传了文件 (通过multer插件)并存储
  • 如果有文件,请上传 到Amazon S3并删除源文件(重要的是要注意我是 在包含S3之前遇到这个问题)。
  • 创建项目 通过推入Firebase上的项目参考
  • 为其创建项目 用户通过推入Firebase上的user_items参考。

我已经将其他一些功能作为API实现。

我的麻烦来自CPU使用率的间歇性高峰,这导致nginx服务器报告来自Node.js应用程序的网关超时。

有时服务器在对MongoDB实例执行身份验证时会崩溃,有时候当我收到来自Mobile应用程序的输入时它会崩溃。它什么时候倒下之间似乎没有任何一致性。有时它适用于15种以上的各种请求(上传/登录/列表等),但有时它会在一次请求后失效。

我添加了以下形式的错误检查:

process.on('uncaughtException', function(err) {
  console.error(err.stack);
});

例如,如果我输错了变量会导致错误,但是当服务器崩溃时,不会抛出任何异常。同样检查我的日志也没什​​么。我已经尝试过分析应用程序,但输出对我来说根本没有任何意义。它并没有特别指向函数或插件。

我很欣赏这是一个冗长的问题,但如果你能指出我调试这个问题的方向,我真的很感激,这让我很头疼!

2 个答案:

答案 0 :(得分:0)

这可能是Firebase库中的错误。你用的是哪个版本?

我一直有一个非常类似的问题让我感到沮丧了好几天。 Heroku上的Node.js + Express + Firebase。进程将运行一段看似随机的时间然后我开始从Heroku获得超时错误,而不会让进程真正崩溃或显示错误。更高的负载似乎不会更快地发生。

我刚从Firebase 1.0.14更新到最新的1.0.19,我认为它可能已经解决了我的问题。过程已经持续了2个小时,之前只能持续5-30分钟。要做更多测试,但我想我会分享我的进展中的结果,以防它们有用。

答案 1 :(得分:0)

似乎答案是因为我的Express应用程序正在为每个请求重用一个Firebase连接,并且由于某种原因导致服务器锁定。

我的解决方案是创建一些基本的中间件,在每个API请求上提供对Firebase的新参考,请参阅下文:

var Middleware = {

    /*
     * Initialise Firebase Refs per connection
     */
    initFireBase: function(req, res, next) {

        console.log('Intialising Firebase for user');

        // We need a authToken
        var authToken = req.param('authToken');

        // Validate the auth token
        if(!authToken || authToken.length === 0) {
            return res.send(500, {code: 'INVALID_TOKEN', message: 'You must supply an authToken to this method.'});
        }
        else {

            // Attempt to parse the auth token
            try {
                var decodedToken = JWTSimple.decode(authToken, serverToken);
            }
            catch(e) {
                return res.send(500, {code: 'INVALID_TOKEN', message: 'Supplied token was not recognised.'});
            }

            // Bail out if the token is invalid
            if(!decodedToken) {
                return res.send(500, {code: 'INVALID_TOKEN', message: 'Supplied token was not recognised.'});
            }

            // Otherwise send the decoded token with the request
            else {
                req.auth = decodedToken.d;
            }

        }

        // Create a root reference
        var rootRef = new Firebase('my firebase url');

        // Apply the references to each request
        req.refs = {
            root: rootRef,
            user: rootRef.child('users'),
            inbox: rootRef.child('inbox')
        };

        // Carry on to the calling function
        next();

    }

};

然后我简单地在我的路线上调用这个中间件:

/*
 * Create a post
 */
router.all('/createPost', Middleware.initFireBase, function(req, res) {

  var refs = req.refs;
  refs.inbox.push({}) // etc

....

此中间件很快将扩展为在连接上提供Firebase.auth(),以确保使用有效的authToken进行的任何API调用都将签署给Firebase的用户。但是对于开发来说这是可以接受的。

希望这有助于某人。