问题
I have a web-app that posts messages on RabbitQueue using spring. I have turned on Publisher confirms and returns enabled and I'm using spring rabbit:template. This is my configuration:
<rabbit:template id="amqpTemplate" connection-factory="amqpConnectionFactory" retry-template="retryTemplate" confirm-callback="messagesConfirmCallback" return-callback="messagesReturnCallback"
exchange="${rabbitmq.rest.exchange}" routing-key="key.listener" mandatory="true" />
<rabbit:connection-factory id="amqpConnectionFactory" publisher-confirms="true" publisher-returns="true" connection-factory="secureClientConnectionFactory" />
<bean id="messagesConfirmCallback" class="com.test.message.MessagesConfirmCallback" />
<bean id="messagesReturnCallback" class="com.test.message..MessagesReturnCallback" />
<bean id="secureClientConnectionFactory" class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean" >
<property name="uri" value="${mq.uri}" />
</bean>
My MessagesConfirmCallback class:
public class MessagesConfirmCallback implements RabbitTemplate.ConfirmCallback {
private static final Log LOGGER = LogFactory.getLog(MessagesConfirmCallback.class);
@Override
public void confirm(CorrelationData correlationData, boolean ack,
String cause) {
if(ack){
LOGGER.info("ACK received");
}
else{
LOGGER.info("NACK received");
}
}
}
and the MessageReturnCallback class:
public class MessageReturnCallback implements RabbitTemplate.ReturnCallback {
private static final Log LOGGER = LogFactory.getLog(MessagesReturnCallback.class);
@Override
public void returnedMessage(Message message, int replyCode,
String replyText, String exchange, String routingKey) {
LOGGER.info("Message: " + message.getBody());
}
}
I am able to see that the MessageReturnCallback.returnedMessage getting invoked (and there by see the published payload) in cases where the publish is successful and ACK is received, but not in case of NACK. Is there a way to get hold of the published message in cases of NACK?
回答1:
When a message is returned because it can't be routed to a queue, RabbitMQ returns the complete message.
When a message is acked (or nacked), RabbitMQ just returns a sequence a number, the whole message is not supplied. Spring AMQP uses that sequence number to determine which correlation data to return.
The application needs to keep a reference to the message before sending (perhaps in a Map, keyed by something in the CorrelationData
, or even in the correlation data itself) so that when the correlation data is supplied in the ack/nack, you can determine which message it is for.
回答2:
When publisher confirm is given by the broker the complete message is not returned but only a correlation data is returned (don't misinterpret it as correlation_id). Developer can pass correlation data when publishing message to broker via rabbitTemplate.send or rabbitTemplate.convertAndSend and the passed correlation data will be sent back by broker. And developer can make a map keyed on correlation data(or id field encapsulated in correlation data) or can store in some database and can retrieve message from there.
来源:https://stackoverflow.com/questions/34125116/spring-rabbittemplate-how-to-get-hold-of-the-published-message-for-nacks-in-pub