Architecture 消息队列体系结构(从客户端到web服务器再到工作服务器)
我有一个在Heroku上运行的用NodeJS编写的web服务器。服务器有一个web服务器进程和一个工作进程。web服务器通过RabbitMQ队列成功地向工作者发送消息;工作进程成功地将处理后的数据返回到web服务器。我使用随机生成的Uuid跟踪消息,并确保正确的消息与正确的原始消息配对 在另一个项目中,我让客户端(网站)成功地与web服务器通信。现在,我需要把两者结合起来 我怎样才能做到这一点:Architecture 消息队列体系结构(从客户端到web服务器再到工作服务器),architecture,rabbitmq,httprequest,backgroundworker,message-queue,Architecture,Rabbitmq,Httprequest,Backgroundworker,Message Queue,我有一个在Heroku上运行的用NodeJS编写的web服务器。服务器有一个web服务器进程和一个工作进程。web服务器通过RabbitMQ队列成功地向工作者发送消息;工作进程成功地将处理后的数据返回到web服务器。我使用随机生成的Uuid跟踪消息,并确保正确的消息与正确的原始消息配对 在另一个项目中,我让客户端(网站)成功地与web服务器通信。现在,我需要把两者结合起来 我怎样才能做到这一点: 客户端发送HTTP POST Web服务器接收请求并将请求传递到消息队列中 Worker处理请求并返
您需要做的简短版本是双向消息传递。您的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) 在某处更新共享数据库,以便您的web服务器知道已完成的工作(并可以读取状态)
或
2) 通过rabbitmq将消息发送回web服务器
出于各种原因,选项1可能并不总是一个好的选项。从你的问题来看,不管怎样,你想要选择2
您需要第二个队列—web服务器正在侦听的队列。当web服务器从该队列接收到消息时,它将使用接收状态更新自己的数据库
此状态可能是“完成”、“进行中”或“错误”或您认为合适的其他状态
例如,如果您有一条“job status”消息,那么您可能有一个名为“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/检查状态”,您将使用相同的“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和Node.js启动并运行它是一个完整的包。尽管它使用的是activeMQ,而不是RabbitMQ,但它在这里说,您使用一个相关id设置每个reach请求,您可以使用该id将响应映射到相应的id,这样,您就可以轻松地用正确的请求响应web客户端。这是一个需要状态更新的长期运行过程吗?或者这是来自后端的一个非常快速的响应,原始HTTP请求应该从该后端服务获得一个带有数据的响应?我认为状态更新。有时,后端将是30秒以上。是的,对于超过一秒左右的时间,状态更新是一种方式。我很快会发布答案。你不能使用WebSocket吗?只要客户留在您的网站上,这应该是可能的。这是一个很好的方法,我想它可以与pub/sub模式混合,而不是池。