使用Spring amqp库的请求-响应模式

使用Spring amqp库的请求-响应模式,spring,rabbitmq,spring-amqp,Spring,Rabbitmq,Spring Amqp,各位。我有一个HTTP API,用于在RabbitMQ代理中发布消息,我需要实现请求-响应模式,以便从服务器接收响应。因此,我是客户机和服务器之间的桥梁。我使用特定的路由密钥将消息推送到代理,并且该消息有一个消费者,该消费者将消息发布回响应,我的API必须为每个请求使用响应。所以这个图表是这样的: 因此,我要做的是:为每个HTTP会话创建一个临时responseQueue(绑定到默认exchange,路由键为该队列的名称),然后将消息的replyTo头设置为响应队列的名称(我将在此处等待响应)

各位。我有一个HTTP API,用于在RabbitMQ代理中发布消息,我需要实现请求-响应模式,以便从服务器接收响应。因此,我是客户机和服务器之间的桥梁。我使用特定的路由密钥将消息推送到代理,并且该消息有一个消费者,该消费者将消息发布回响应,我的API必须为每个请求使用响应。所以这个图表是这样的:

因此,我要做的是:为每个HTTP会话创建一个临时responseQueue(绑定到默认exchange,路由键为该队列的名称),然后将消息的replyTo头设置为响应队列的名称(我将在此处等待响应)并将模板replyQueue设置为该队列。这是我的密码:

public void sendMessage(AbstractEvent objectToSend, final String routingKey) {
    final Queue responseQueue = rabbitAdmin.declareQueue();
    byte[] messageAsBytes = null;
    try {
        messageAsBytes = new ObjectMapper().writeValueAsBytes(objectToSend);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    MessageProperties properties = new MessageProperties();
    properties.setHeader("ContentType", MessageBodyFormat.JSON);
    properties.setReplyTo(responseQueue.getName());
    requestTemplate.setReplyQueue(responseQueue);

    Message message = new Message(messageAsBytes, properties);
    Message receivedMessage = (Message)requestTemplate.convertSendAndReceive(routingKey, message);
}
那么问题是什么呢:消息被发送,之后它被使用者使用,并且它的响应被正确地发送到正确的队列,但是由于某种原因,它没有在ConvertSendReceived方法中收回,并且在设置的超时之后,我的receivedMessage为null。所以我试着做了几件事——我开始检查spring代码(顺便说一句,这样做真是一场噩梦),发现我没有声明它为我创建的响应队列,replyTo头被设置为队列的名称(与我所做的相同)。结果是相同的-receivedMessage仍然为null。之后,我决定使用另一个使用默认exchange的模板,因为responseQueue绑定到该exchange:

requestTemplate.send(routingKey, message);
Message receivedMessage = receivingTemplate.receive(responseQueue.getName());
结果相同-responseMessage仍然为空。
amqp和rabbit的版本分别为1.2.1和1.2.0。因此,我确信我错过了一些东西,但我不知道是什么,因此如果有人能帮助我,我将不胜感激。

1>奇怪的是,
rabbitmplate
使用
doSendAndReceiveWithFixed
如果您提供
requestTemplate.setReplyQueue(responseQueue)
。看来你的解释是错误的

2> 要使用fixed
ReplyQueue
,您应该配置一个
reply
ListenerContainer

SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(rabbitConnectionFactory);
container.setQueues(responseQueue);
container.setMessageListener(requestTemplate);
3> 但是这里最重要的部分是关于相关性的。
rabbitmplate.send和receive
填充了
correlationId
消息属性,但是消费者方面也必须处理它:仅仅向
responseQueue
发送回复是不够的,回复消息应该具有相同的
correlationId
属性。请看这里:


顺便说一句,没有理由手动填充
消息
:您只需支持
Jackson2JsonMessageConverter
rabbitmplate
,它就会自动将
objectToSend
转换成带有适当头的JSON字节。

是的,我遗漏的重要部分是您提到的correlationId。我在发回回复时忘了设置。谢谢!