2

Express を使用してノード内のドメインとクラスターをいじっていて、この状況に陥りました。コアごとにワーカーを生成するクラスターがあり、ワーカーごとに、リクエストごとのドメイン戦略を使用してエラーを処理するエクスプレスサーバーを作成します。

以下に示す解決策はそのままでは正常に機能しますが、ドメインにリクエスト オブジェクトとレスポンス オブジェクトを明示的に追加すると、エラー ミドルウェアの呼び出しが停止します。この動作が導入される理由がわかりません。

質問:

  1. なぜ起こっているのですか?
  2. ドメインを正しい方法で使用していますか?
  3. 「process.domain」を介してワーカーの現在のドメインにアクセスできますか、それとも別のことをする必要がありますか?

前もって感謝します!

私のapp.js:

var express = require('express')
  , http = require('http')
  , path = require('path')
  , domain = require('domain')
  , cluster = require('cluster')
  , http = require('http')
  , numCPUs = require('os').cpus().length;

if (cluster.isMaster) {

  // fork workers
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  // when a worker dies create a new one
  cluster.on('exit', function(worker, code, signal) {
    cluster.fork();
  });

} else {

  var app = express();

  //domains
  app.use(function domainMiddleware(req, res, next) {

    var reqDomain = domain.create();

    res.on('close', function () {
      reqDomain.dispose();
    });

    res.on('finish', function () {
      reqDomain.dispose();
    });

    reqDomain.on('error', function (err) {
      reqDomain.dispose();
      // delegate to express error-middleware
      next(err);
    });

    // Adding the request and response objects to the domain
    // makes the express error-middleware to not being called.
    // reqDomain.add(req);
    // reqDomain.add(res);

    reqDomain.run(next);
  });

  // all environments
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  //app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));

  // for testing which cluster that serves the request
  app.get('/', function(req, res, next) {
    res.json(200, { id: cluster.worker.id });
  });
  app.get('/error', function(req, res, next) {
    var fs = require('fs');
    // intentionally force an error
    fs.readFile('', process.domain.intercept(function(data) { 
      // when using intercept we dont need this line anymore
      //if (err) throw err;
      res.send(data);
    }));
  });

  app.use(function(err, req, res, next) {
    console.log('ERROR MIDDLEWARE', err);
    res.writeHeader(500, {'Content-Type' : "text/html"});
    res.write("<h1>" + err.name + "</h1>");
    res.end("<p>" + err.message + "</p>");
  });

  http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
  });
}
4

1 に答える 1