我正在复制NodeJS中的EasyNetQ功能(这样Node应用程序就可以通过支持EasyNetQ的.NET应用程序与Rabbit通信)。我已经复制了EasyNetQ的发布/订阅和EasyNetQ的发送/接收,但我在使用EasyNetQ的请求/响应方面遇到了一些困难。
这是我当前的节点代码:
var rqrxID = uuid.v4(); //a GUID
var responseQueue = 'easynetq.response.' + rqrxID;
Q(Play.AMQ.ConfirmChannel.assertQueue(responseQueue, { durable: false, exclusive: true, autoDelete: true }))
.then((okQueueReply) =>
Play.AMQ.ConfirmChannel.consume(responseQueue, (msg) => {
//do something here...
Play.AMQ.ConfirmChannel.ack(msg);
})
)
.then((okSubscribeReply) => {
Q(Play.AMQ.ConfirmChannel.assertExchange('easy_net_q_rpc', 'direct', { durable: true, autoDelete: false }))
.then((okExchangeReply) =>
Play.AMQ.ConfirmChannel.publish(
global.AppConfig.amq.rpc.exchange,
dto.AsyncProcessorCommand.Type,
Play.ToBuffer(command),
{ type: command.GetType() },
(err, ok): void => {
if (err !== null) {
console.warn('Message nacked!');
responseDeferred.reject(err);
}
}
)
)
})
.catch((failReason) => {
console.error(util.format('Error creating response queue: %s', failReason));
return null;
});
请注意,发布有效,并由.NET代码接收。该代码然后发送响应,问题是没有收到响应。这是.NET代码:
Bus.Respond<AsyncProcessorCommand, AsyncProcessorCommandResponse>(
request =>
{
Console.WriteLine("Got request: '{0}'", request);
return new AsyncProcessorCommandResponse()
{
ID = Guid.NewGuid(),
ResponseType = "ENQResp"
};
});
我确定我错过了什么,但不确定是什么。谁可以帮忙?
更新 我已经解决了至少部分问题。获取responseQueue的值并将其设置为发布选项“replyTo”将响应挂起 - 很好。现在我只需弄清楚如何在每次 OR 时都不创建新队列,让响应队列消失......
更新最终 因此,使用我拥有的频道设置并保存cinsumerTag(实际上,指定它)允许我取消消费者并自动删除队列。
答案 0 :(得分:0)
从上面的评论中回答这个问题。
这有两件事。首先,从上面的代码中,创建您的响应队列,以便自动删除(当使用者计数降至0时):
channel.assertQueue(responseQueue, { durable: false, exclusive: true, autoDelete: true }))
然后创建/发布到“服务器”正在侦听的队列 - 确保为刚刚创建的响应队列设置“replyTo”(类型块是另一个需要ENQ的代码):
{ type: command.GetType(), replyTo: responseQueue }
因此执行此模式的整个(当前是“播放”代码的混乱)方法如下所示:
private static Request(command: dto.AsyncProcessorCommand): Q.Promise<dto.interfaces.IAsyncProcessorCommandResponse> {
var responseDeferred = Q.defer<dto.interfaces.IAsyncProcessorCommandResponse>();
var consumerTag = uuid.v4();
var rqrxID = uuid.v4();
var responseQueue = 'easynetq.response.' + rqrxID;
var handleResponse = (msg: any): void => {
var respType = null;
switch(command.Action) {
default:
respType = 'testResp';
}
//just sending *something* back, should come from 'msg'
responseDeferred.resolve(new dto.AsyncProcessorCommandResponse(respType, { xxx: 'yyy', abc: '123' }));
}
Q(Play.AMQ.ConfirmChannel.assertQueue(responseQueue, { durable: false, exclusive: true, autoDelete: true }))
.then((okQueueReply) =>
Play.AMQ.ConfirmChannel.consume(responseQueue, (msg) => {
handleResponse(msg);
Play.AMQ.ConfirmChannel.ack(msg);
Play.AMQ.ConfirmChannel.cancel(consumerTag);
},
{ consumerTag: consumerTag })
)
.then((okSubscribeReply) => {
Q(Play.AMQ.ConfirmChannel.assertExchange('easy_net_q_rpc', 'direct', { durable: true, autoDelete: false }))
.then((okExchangeReply) =>
Play.AMQ.ConfirmChannel.publish(
'easy_net_q_rpc',
dto.AsyncProcessorCommand.Type,
Play.ToBuffer(command),
{ type: command.GetType(), replyTo: responseQueue },
(err, ok): void => {
if (err !== null) {
console.warn('Message nacked!');
responseDeferred.reject(err);
}
}
)
)
})
.catch((failReason) => {
console.error(util.format('Error creating response queue: %s', failReason));
return null;
});
return responseDeferred.promise
}