Node.js 将req和res显式添加到域don';t传播错误以表示中间件
我正在用express在node中玩域和集群,并陷入了这种情况。我有一个集群,每个核心生成一个worker,我为每个worker创建一个express服务器,该服务器使用每个请求的域策略来处理错误 下面给出的解决方案可以正常工作,但是当向域显式添加请求和响应对象时,错误中间件将停止调用。我不知道为什么会出现这种行为 问题:Node.js 将req和res显式添加到域don';t传播错误以表示中间件,node.js,express,Node.js,Express,我正在用express在node中玩域和集群,并陷入了这种情况。我有一个集群,每个核心生成一个worker,我为每个worker创建一个express服务器,该服务器使用每个请求的域策略来处理错误 下面给出的解决方案可以正常工作,但是当向域显式添加请求和响应对象时,错误中间件将停止调用。我不知道为什么会出现这种行为 问题: 为什么会这样 我是否以正确的方式使用域 我可以通过“process.domain”访问工作进程中的当前域吗 还是我需要做些不同的事情 提前谢谢 我的app.js: var e
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'));
});
}
var express=require('express'))
,http=require('http')
,path=require('path'))
,domain=require('domain')
,cluster=require('cluster'))
,http=require('http')
,numpus=require('os').cpus().length;
if(cluster.isMaster){
//叉工
对于(变量i=0;i”);
});
http.createServer(app.listen)(app.get('port'),function(){
console.log('Express server监听端口'+app.get('port'));
});
}
这是由于调用了reqDomain.dispose()
。从:
dispose方法销毁域,并尽最大努力清理与该域关联的所有IO。流被中止、结束、关闭和/或销毁。计时器被清除。显式绑定的回调不再被调用。因此引发的任何错误事件都将被忽略
将req
和res
添加到域后,处理域。您可以通过在('error')回调上,但在处理域之前,显式地将一些输出发送到res
中的reqDomain.on('error')
回调来测试这一点
只需将调用移动到next
一行就可以解决问题:
reqDomain.on('error', function (err) {
next(err);
reqDomain.dispose();
});
至于
process.domain
,我以前从未见过这种方法,并且对它的有效性感到非常惊讶。我查看了源代码并:
因此,
process.domain
似乎总是“最新”的域。就个人而言,我可能会将域附加到req
对象或其他对象上,这样您就可以更明确地知道哪个域应该处理错误(尽管实际上可能是过程。域始终是您要查找的域)。谢谢您的回答!通过将调用“next(err)”向上移动一行,您的正确操作将解决此问题,尽管可以在下一个中间件中触发某些异步操作之前释放req和res对象。我正在摆弄一个解决方案,在所有中间件的末尾放置一个错误中间件来处理域,但我得到了一些奇怪的结果。显然,当您将REQ和RES对象添加到域时,它们将得到与它们相关联的域,即“REQ.DealEnter”属性将被设置。你是对的,退房。我想,总体而言,域代码应该是很好的翻阅(虽然图片中的某些部分是这样的,但它并不太长)。
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);
};