使用Mean.js中的节点域

时间:2015-07-06 22:48:21

标签: node.js error-handling meanjs

我正在努力让我的MEAN应用程序准备好进行生产。该应用程序构建在Mean.js样板上。根据我的理解,MEAN.js在发生错误后使用Forever.js重新启动应用程序(虽然严格缺乏准备用于生产的Mean.js的文档);但是,似乎处理应用程序崩溃的建议方法是将Node&域与群集结合使用。以下是一些参考文献:

  • 这是来自已弃用 uncaughtException活动的节点网页:
  

请注意,uncaughtException是一种非常粗略的异常处理机制。

     

不要使用它,而是使用域名。

虽然我已经找到了许多使用域名的建议,但我还没有找到一个告诉我在应用程序中合并域名需要做些什么,特别是已经开发过的域名。

问题

  • 将节点域集成到Mean.js应用程序需要做什么?根据我收集的内容(来自Node.js域名网页和here),您将进入Mean.js项目根目录中的server.js并执行与此类似的操作:

    var cluster = require('cluster');
    var PORT = +process.env.PORT || 1337;
    
    if (cluster.isMaster) {
      //Fork the master as many times as required.
      cluster.fork();
      cluster.fork();
    
      cluster.on('disconnect', function(worker) {
        console.error('disconnect!');
        cluster.fork();
      });
    
    } else {    
      var domain = require('domain');
      var d = domain.create();
      d.on('error', function(er) {
        console.error('error', er.stack);
    
        try {
          // make sure we close down within 30 seconds
          var killtimer = setTimeout(function() {
            process.exit(1);
          }, 30000);
          // But don't keep the process open just for that!
          killtimer.unref();
    
          // stop taking new requests.
          server.close();
    
          // Let the master know we're dead.  This will trigger a
          // 'disconnect' in the cluster master, and then it will fork
          // a new worker.
          cluster.worker.disconnect();
    
          // try to send an error to the request that triggered the problem
          res.statusCode = 500;
          res.setHeader('content-type', 'text/plain');
          res.end('Oops, there was a problem!\n');
        } catch (er2) {
          // oh well, not much we can do at this point.
          console.error('Error sending 500!', er2.stack);
        }
      });
    
      d.run(function() {
        //Place the current contents of server.js here.
      });
    }
    
  • 我是否需要在domain.run()中包装所有后端控制器?

1 个答案:

答案 0 :(得分:1)

这个答案是通过实验和更多的挖掘找到的。我必须同时修改server.jsconfig/express.js才能使用域名。该域是每个请求的Express中间件的一部分。 不要在问题中使用代码,它不会按原样运行。

首先,我对server.js所做的更改:

var init = require('./config/init')(),
    config = require('./config/config'),
    mongoose = require('mongoose'),
    cluster = require('cluster');

var processes = 4;    //Number of processes to run at the same time.

if(cluster.isMaster) {
    for(var i = 0; i < processes; i++) {
        cluster.fork();
    }

    cluster.on('disconnect', function(worker) {
        console.error("Disconnect!");
        cluster.fork();
    });
} else {
    /**
     * Main application entry file.
     * Please note that the order of loading is important.
     */

    // Bootstrap db connection
    var db = mongoose.connect(config.db, function(err) {
        if (err) {
            console.error('\x1b[31m', 'Could not connect to MongoDB!');
            console.log(err);
        }
    });

    // Init the express application
    var expressConfig = require('./config/express');
    var app = expressConfig.initialize(db);

    app.use(function(err, req, res, next) {
      console.error(err);
      res.send(401).json({your_message_buddy: "Nice try, idiot."});
    });


    // Bootstrap passport config
    require('./config/passport')();

    // Start the app by listening on <port>
    expressConfig.setServer(app.listen(config.port));

    // Expose app
    exports = module.exports = app;

    // Logging initialization
    console.log('MEAN.JS application started on port ' + config.port);
}

config/express.js的必要更改:

var domain = require('domain'),
    cluster = require('cluster');

var appServer = null;

module.exports = {};

/**
* Since we begin listening for requests in server.js, we need a way to
* access the server returned from app.listen() if we want to close the
* server after an error.  To accomplish this, I added this function to
* pass the server object after we begin listening.
*/
module.exports.setServer = function(server) {
    appServer = server;
};

module.exports.initialize = function(db) {
    //Initialize express app
    var app = express();

    //Globbing model files
    config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) {
        require(path.resolve(modelPath));
    });

    //Set up domain for request BEFORE setting up any other middleware.
    app.use(function(req, res, next) {
        //Create domain for this request
        var reqdomain = domain.create();
        reqdomain.on('error', function(err) {
            console.error('Error: ', err.stack);

            try {
                //Shut down the process within 30 seconds to avoid errors.
                var killtimer = setTimeout(function() {
                    console.error("Failsafe shutdown.");
                    process.exit(1);
                }, 30000);

                //No need to let the process live just for the timer.
                killtimer.unref();

                //No more requests should be allowed for this process.
                appServer.close();

                //Tell master we have died so he can get another worker started.
                if(cluster.worker) {
                    cluster.worker.disconnect();
                }

                //Send an error to the request that caused this failure.
                res.statusCode = 500;
                res.setHeader('Content-Type', 'text/plain');
                res.end('Oops, there was a problem.  How embarrassing.');
            } catch(err2) {
                //Well, something is pretty screwed up.  Not much we can do now.
                console.error('Error sending 500!\nError2: ', err2.stack);
            }
        });

        //Add request and response objects to domain.
        reqdomain.add(req);
        reqdomain.add(res);

        //Execute the rest of the request chain in the domain.
        reqdomain.run(next);
    });

    //The rest of this function, which used to be module.exports, is the same.
};