之前,我已经问过有关此主题的一些常规问题(节点和阻止)。这次问题更加具体了。

假设我有一个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和网络库编写的。这些库强制执行异步流。包的作者必须竭尽全力使其保持同步。

09-30 16:00
查看更多