Skip to content

Instantly share code, notes, and snippets.

@pmihalcin
Last active November 7, 2022 14:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pmihalcin/32e918d029c15287ea345f1c8960b135 to your computer and use it in GitHub Desktop.
Save pmihalcin/32e918d029c15287ea345f1c8960b135 to your computer and use it in GitHub Desktop.
Rabbit publisher confirms or transactions

AMQP AcknowledgeMode

public static final AcknowledgeMode AUTO

  • Auto - the container will issue the ack/nack based on whether the listener returns normally, or throws an exception.
  • Do not confuse with RabbitMQ autoAck which is represented by NONE here.

The AUTO is involved in the commitIfNecessary() which is called only when your target listener returns normally

https://docs.spring.io/spring-amqp/reference/html/_reference.html#template-confirms

https://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/

https://www.rabbitmq.com/confirms.html#publisher-confirms

https://docs.spring.io/spring-amqp/reference/html/_reference.html#transactions

https://github.com/spring-projects/spring-amqp-samples/tree/master/spring-rabbit-confirms-returns

Publisher confirms

spring.rabbitmq.publisher-confirms=true

No, that isn't good practice to always use Publisher Confirms. You lose a bit in performance and throughput. Since there should be run some mechanism on the Broker to notify you about those particular events.

It depends on the use case; if you want guaranteed delivery then, yes, they can be used; they are significantly more efficient than using transactions (by several hundred times).

  • ack is for the consumer side - therefore Listener Container is there for you
  • The publisher-returns is up to producer - therefore RabbitTemplate

If you publish a message with a RabbitTemplate that has setChannelTransacted(true), it's about 250x slower than without it. Sometimes transactions are needed but often publisher confirms are sufficient - however, if you block the sending thread and wait for the confirmation, it won't be much faster than using transactions. Publisher confirms come into their own when you publish a bunch of messages and then later wait for the confirmations.

If performance is not a concern then the simplest config is to enable channelTransacted on both the listener container (inbound adapter) and template (outbound adapter). Then, the container will start a transaction, receive a message; any downstream publishing on the container thread will participate in the transaction. If the flow finishes normally, the message will be ack'd and the transaction committed. Receiving the message is not part of the transaction, but the ack is.

Dealing with publisher confirms adds complexity (and won't help much with performance if you want to wait for the confirm on a single message).

https://docs.spring.io/spring-amqp/reference/html/_reference.html#_introduction_13

The primary reconnection features are enabled by the CachingConnectionFactory itself. It is also often beneficial to use the RabbitAdmin auto-declaration features. In addition, if you care about guaranteed delivery, you probably also need to use the channelTransacted flag in RabbitTemplate and SimpleMessageListenerContainer and also the AcknowledgeMode.AUTO (or manual if you do the acks yourself) in the SimpleMessageListenerContainer.

https://docs.spring.io/spring-amqp/reference/html/_reference.html#async-listeners

How would you test that message doesn't arrive to given AMQP queue?

https://docs.spring.io/spring-amqp/docs/2.0.3.RELEASE/reference/html/_reference.html#template-confirms

If you send a mandatory message to an exchange that can't route to a queue; you get a returned message followed by an ack - the ack meaning it reached an exchange.

https://www.rabbitmq.com/confirms.html#when-publishes-are-confirmed

As also stated on that page nacks generated by the broker are rare (means there is a bug in the broker). However, Spring AMQP will synthesize a nack if there is an outstanding ack and something caused the channel to close before the ack was received.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment