gpt4 book ai didi

node.js - 显式添加 req 和 res 到域不会将错误传播到 Express 中间件

转载 作者:太空宇宙 更新时间:2023-11-03 22:02:29 24 4
gpt4 key购买 nike

我正在使用 Express 来处理 Node 中的域和集群,并遇到了这种情况。我有一个集群,每个核心生成一个工作程序,对于每个工作程序,我创建一个快速服务器,它使用每个请求域策略来处理错误。

下面给出的解决方案按原样工作正常,但是当显式地将请求和响应对象添加到域时,错误中间件停止被调用。我不知道为什么会引入这种行为。

问题:

  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'));
});
}

最佳答案

这是由于调用了 reqDomain.dispose()。来自 dispose documentation :

The dispose method destroys a domain, and makes a best effort attempt to clean up any and all IO that is associated with the domain. Streams are aborted, ended, closed, and/or destroyed. Timers are cleared. Explicitly bound callbacks are no longer called. Any error events that are raised as a result of this are ignored.

reqres 添加到域后,将处置域 ends/closes/destroys them 。您可以通过在 reqDomain.on('error') 回调内向 res 显式发送一些输出来测试这一点,但在处置域之前。

只需将调用移动到 next 上一行似乎就可以解决问题:

reqDomain.on('error', function (err) {
next(err);
reqDomain.dispose();
});
<小时/>

至于process.domain,我以前没有见过这个,并且对它的工作原理感到非常惊讶。我查看了源代码,found the following :

Domain.prototype.enter = function() {
if (this._disposed) return;

// note that this might be a no-op, but we still need
// to push it onto the stack so that we can pop it later.
exports.active = process.domain = this;
stack.push(this);
};

因此,process.domain 似乎始终是“最新”域。就我个人而言,我可能会将域附加到 req 对象或其他东西,以便您可以更明确地了解哪个域应该处理错误(尽管实际上可能是那个 process.域始终是您要查找的域)。

关于node.js - 显式添加 req 和 res 到域不会将错误传播到 Express 中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16763550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com