【问题标题】:Debug Node.js & Express App - Intermittently using 100% CPU调试 Node.js 和 Express 应用程序 - 间歇性地使用 100% CPU
【发布时间】:2014-08-13 16:33:14
【问题描述】:

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

简单来说,“create”函数就是这样做的

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

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

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

有时服务器会在对 MongoDB 实例执行身份验证时发生故障,有时在我从移动应用程序接收输入时服务器会发生故障。它跌倒时似乎没有任何一致性。有时它适用于 15 多个不同的请求(上传/登录/列表等),但有时它会在一个请求后崩溃。

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

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

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

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

【问题讨论】:

  • Bugger 可能会有所帮助。您使用 Chrome 开发工具来访问它。
  • 感谢您的回复,但bugger 不会在我的服务器上启动,即使我是 root,也会抛出 ECONNREFUSED。已经查看了节点检查器,但它没有让我对网络选项卡有任何可见性,我认为这对于了解是否是导致它的任何外部调用至关重要。
  • 您是否尝试过使用 New Relic 之类的工具来帮助检查您的应用?
  • 感谢您的想法。我已经安装了它,但 New Relic 似乎没有返回太多的使用数据。我会一直安装它以防万一。

标签: node.js express nginx firebase


【解决方案1】:

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

我遇到了一个非常相似的问题,让我沮丧了好几天。 Heroku 上的 Node.js + Express + Firebase。进程将运行看似随机的时间,然后我开始从 Heroku 收到超时错误,而进程实际上没有崩溃或显示错误。更高的负载似乎不会让它更快发生。

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

【讨论】:

  • 非常感谢您的回复。我一直在使用 Firebase 1.0.19 进行开发 - 但我已经使用一些我将在我的答案中详述的方法重建了应用程序,并且它还没有崩溃(24 小时 +)
【解决方案2】:

答案似乎与我的 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 端的用户。但是对于开发来说,这是可以接受的。

希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2012-07-17
    • 2020-07-31
    相关资源
    最近更新 更多