2014-07-16 42 views
5

everyone。我有一個用於在RabbitMQ代理中發佈消息的HTTP API,我需要實現請求 - 響應模式才能接收來自服務器的響應。所以我就像是客戶端和服務器之間的橋樑。我使用特定的路由密鑰將消息推送給代理,並且消息中有一個消費者,它將發佈消息作爲響應,我的API必須消耗每個請求的響應。所以,該圖是這樣的:使用Spring amqp庫的請求響應模式

Request-Response pattern

所以我要做的就是以下各項爲我創建一個臨時responseQueue(這勢必會默認交換每個HTTP會話,用路由關鍵的,這個名字隊列),之後我將消息的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方法中,並在設置超時後,我的receivedMessage爲null。所以我試着做了幾件事情 - 我開始檢查Spring代碼(通過這樣做真是一場噩夢),並且看到我沒有聲明響應隊列,它爲我創建了一個臨時表,並且replyTo標題被設置爲隊列的名稱(與我所做的相同)。結果是一樣的 - receivedMessage仍然爲空。從那以後,我決定使用使用默認交換另一個模板,因爲responseQueue綁定到交換:

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

結果是各項─的responseMessage仍然是空。 amqp和rabbit的版本分別爲1.2.1和1.2.0。所以我肯定我錯過了一些東西,但我不知道它是什麼,所以如果有人能幫助我,我會非常感激。

回答

2

1>如果您提供requestTemplate.setReplyQueue(responseQueue),很奇怪RabbitTemplate使用doSendAndReceiveWithFixed。看起來你的解釋是錯誤的。

2>,使其與固定ReplyQueue工作,你應該配置一個replyListenerContainer

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:你可以只是簡單的支持Jackson2JsonMessageConverterRabbitTemplate,它會將您的objectToSend到JSON適當的標題自動字節。

+0

是的,我錯過的重要部分就是你提到的correlationId。當我回復回復時,我忘了設置它。非常感謝! –