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

时间:2014-07-16 15:23:31

标签: spring rabbitmq spring-amqp

大家。我有一个HTTP API用于在RabbitMQ代理中发布消息,我需要实现请求 - 响应模式,以便从服务器接收响应。所以我就像是客户端和服务器之间的桥梁。我使用特定的路由密钥将消息推送到代理,并且有消息用于消息,它将按摩作为响应发布回来,我的API必须消耗每个请求的响应。所以图表是这样的:

Request-Response pattern

所以我做的是以下内容 - 对于每个HTTP会话,我创建一个临时的responseQueue(绑定到默认交换,路由键是该队列的名称),之后我将消息的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);
}

那么问题是什么:消息被发送,之后它被消费者使用并且其响应被正确地发送到正确的队列,但由于某种原因它不会被回收在convertSendAndReceived方法中并且在集合之后timeout我的receivedMessage为null。所以我试着做了几件事 - 我开始检查弹簧代码(顺便说一下,这是一个真正的噩梦)并且看到我没有声明它为我创建一个时间的响应队列,以及replyTo头设置为队列的名称(与我的相同)。结果是相同的 - receivedMessage仍为null。之后我决定使用另一个使用默认交换的模板,因为responseQueue绑定到该交换:

requestTemplate.send(routingKey, message);
Message receivedMessage = receivingTemplate.receive(responseQueue.getName());

结果相同 - responseMessage仍然为null。 amqp和兔子的版本分别为1.2.1和1.2.0。所以我确信我会错过一些东西,但我不知道它是什么,所以如果有人可以帮助我,我将非常感激。

1 个答案:

答案 0 :(得分:2)

1>如果您提供RabbitTemplate,则doSendAndReceiveWithFixed使用requestTemplate.setReplyQueue(responseQueue)会很奇怪。看起来你的解释是假的。

2 - ;要使其与固定ReplyQueue一起使用,您应配置reply ListenerContainer

SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(rabbitConnectionFactory);
container.setQueues(responseQueue);
container.setMessageListener(requestTemplate);

3>但这里最重要的部分是correlationRabbitTemplate.sendAndReceive填充correlationId消息属性,但消费者方也必须处理它:仅仅发送回复responseQueue,回复消息是不够的应具有相同的correlationId属性。见这里:how to send response from consumer to producer to the particular request using Spring AMQP?

BTW没有理由手动填充Message:您只需支持Jackson2JsonMessageConverter RabbitTemplate即可自动将objectToSend转换为JSON字节有适当的标题。