您需要做的简短版本是双向消息传递。您的 Web 应用程序需要是消息生产者和消息消费者。您的后端服务也是如此。
当 HTTP 请求进来时,Web 服务器通过 RabbitMQ 发送消息。后端会在未来的某个时间点接收它。同时,Web 服务器通过 HTTP 请求发回响应,说明正在发生某些事情,稍后将通知用户。
如果您使用的是 express,它看起来像这样:
var router = express.Router();
router.post("/", postJob);
function postJob(req, res, next){
req.session.inProgress = true;
var msg = {
job: "do some work"
};
jobSender.sendJobRequest(msg, function(err){
if (err) { return next(err); }
res.render("some-response");
});
}
这段代码做了很多假设,比如jobSender 是某种封装对象,具有通过 RabbitMQ 发送消息的方法。根据您已经说过的,我相信您可以填写发送消息的详细信息。
重要的是,HTTP 请求处理程序通过 RabbitMQ 发送消息,然后将 HTTP 响应发送回 Web 浏览器。
此时,浏览器可以做它需要做的任何事情。
在后端,当其他服务完成它的工作时,它需要做以下两件事之一:
1) 在某处更新共享数据库,以便您的网络服务器知道已完成的工作(并且可以读取状态)
或
2) 通过 rabbitmq 将消息发送回 Web 服务器
由于各种原因,选项#1 可能并不总是一个好的选择。从你的问题来看,无论如何你都想要选项#2。
您将需要第二个队列 - Web 服务器正在侦听的队列。当 Web 服务器从该队列接收到消息时,它将使用接收到的状态更新它自己的数据库。
此状态可能是“完成”或“进行中”或“错误”或您认为合适的其他状态。
例如,如果您有一个“工作状态”消息,您可能有一个名为“JobStatusReceiver”的抽象来接收状态消息。
像这样的简单模块可以从您的作业状态队列接收消息,并使用状态更新本地数据库
var JobStatusReceiver = require("./jobStatusReceiver");
var someDataObject = require("someDataObject");
var jobStatus = {
listen: function(){
var receiver = new JobStatusReceiver();
receiver.receive(function(statusMessage){
someDataObject.status = statusMessage.status;
someDataObject.data = statusMessage.data;
someDataObject.save();
});
}
};
module.exports = jobStatus;
请注意,这可能发生在 Web 服务器中,但它不是 HTTP 请求的一部分。消息通过带有 JobStatusReceiver 的 RabbitMQ 传入,而不是 HTTP 请求的一部分。
someDataObject 对象很可能是来自 yoru 数据库的对象,因此可以将其保存回数据库。
最后,您需要通过数据通知用户已完成操作的部分可以通过多种方式进行。
一般来说,每隔几秒对 Web 服务器上的 HTTP API 进行一次 AJAX 调用以查找有效响应是相当容易的。
在浏览器端,这可能很简单:
var timer = setInterval(function(){
$.ajax({
url: "/api/check-status",
success: function(data){
if (data.complete){
clearInterval(timer);
doSomeOtherWork(data);
}
})
});
});
再次在 Express 应用程序中,处理“/api/check-status”,您将使用相同的“someDataObject”模型来检查状态:
var someDataObject = require("someDataObject");
var router = new express.Router();
router.get("/", checkStatus);
function checkStatus(req, res, next){
someDataObject.load(function(err, someData){
if (err) { return next(err); }
res.json({
complete: (someData.status === "complete"),
data: someData.data
});
});
}
希望这能让您走上正确的道路。当然,我遗漏了很多细节,但希望您能够填补缺失的部分。
...
P.S.:我在RabbitMQ 4 Devs 培训课程中涵盖了所有这些,除了浏览器在计时器上检查状态更新。这是一个使用 RabbitMQ 和 Node.js 启动和运行的完整包