之前,我已经问过有关此主题的一些常规问题(节点和阻止)。这次问题更加具体了。
假设我有一个node / express应用,该应用的句柄正在接受HTTP请求(没关系,说它们是简单的GET)。
它具有一个单独的处理程序,该处理程序在到达消息时从RabbitMQ队列中读取消息,然后从Mongo中进行读取(Mongo在另一台计算机上),然后进行写入。
如果Mongo“非常”忙,会/是否会导致HTTP处理程序不可用?
我正在使用Mongo本机驱动程序。我认为Mongo驱动程序等待服务器响应时发生的任何阻塞都会使Node开心地接受和处理HTTP请求,但是我不确定。
在相关场景中,将忙碌的Mongo换出为处理程序,该处理程序读取Rabbit消息并将记录放入“非常忙碌的ElasticSearch”中。这会导致HTTP处理程序出现问题吗?
我将直接对其进行测试,但这有点棘手,并且每次我不确定理论是什么时,都会进行昂贵的测试。所以我想问一下。
这是代码的(简化)示例:
// HTTP handler...
app.post('/eventcapture/event', (req: express.Request, res: express.Response) => {
var evt: eventDS.IEvent = ('TypeID' in req.body) ? req.body : JSON.parse(req.body);
//create an id
evt._id = uuid.v4();
bus.Publish(evt)
.then((success) => {
res.jsonp(200, { success: true });
})
.catch((failReason:Error) => {
console.error('[ERROR] - Failure writing event: %s,%s', failReason.name, failReason.message);
logError(failReason, evt);
res.jsonp(500, { success: false, reason: failReason });
});
});
// We generically define additional handlers in an array, and then kick them off with a loop.
// Here we have one handler which reads an event, goes to mongo to get additional data which
// it adds into the event before publishing it back out. And a second handler which will catch
// these "augmented" events and push them into Mongo
var processes = [
{
enabled: true,
name: 'augmenter',
inType: 'EventCapture:RawEvent',
handler: (event: eventDS.IEvent) => {
console.log('[LOG] - augment event: %s', event._id);
Profile.FindOne({ _id: event.User.ProfileID })
.then((profile) => {
if (profile) {
console.log('[LOG] - found Profile: %s', profile._id);
event.User.Email = profile.PersonalDetail.Email;
//other values also...
//change the TypeID for publishing
event.TypeID = 'EventCapture:AugmentedEvent';
return event;
}
else throw new Error(util.format('unable to find profile: %s', event.User.ProfileID));
})
.then((augmentedEvent) => bus.Publish(augmentedEvent)) //publish the event back out
.catch((failReason:Error) => {
console.error('[ERROR] - failure publishing augmented event: %s, %s, %s', event._id, failReason.name, failReason.message);
logError(failReason, event);
});
}
},
{
enabled: true,
name: 'mongo',
inType: 'EventCapture:AugmentedEvent',
handler: (event: eventDS.IEvent) => {
console.log('[LOG] - push to mongo: %s', event.User.ProfileID);
Event.Save(event, { safe: true })
.then((success) => console.log('[LOG] - pushed to mongo: %s', event._id))
.catch((failReason:Error) => {
console.error('[ERROR] - failure pushing to mongo: %s, %s', event._id, failReason);
logError(failReason, event);
});
}
}
];
processes.forEach((process, idx, allProcesses) => {
if (process.enabled) {
bus.Subscribe(process.name, process.inType, process.handler);
}
});
最佳答案
不,这是异步编程的精妙之处。节点在等待mongodb返回节点时可以执行其他操作。您可以假设流行的节点模块(例如mongodb)以异步方式编写内容。
这是一个详细介绍事件循环的视频:http://vimeo.com/96425312?utm_source=nodeweekly&utm_medium=email
最终,诸如mongo驱动程序之类的事情是使用节点的底层io和网络库编写的。这些库强制执行异步流。包的作者必须竭尽全力使其保持同步。