Search code examples
spring-amqpspring-rabbitrabbitmq-cluster

Spring AMQP connecting to cluster with LB DNS - use single or multiple addresses?


My code will try to connect to an CloudAMQP 3-node cluster, which provides 2 flavours of DNS names:

  1. A record that returns 3 IP addresses.
  2. Three records that returns each of the underlying IP address. Example:
PS C:\Users\LiuSean> nslookup funny-plum-koala.rmq2.cloudamqp.com
...

Non-authoritative answer:
Name:    funny-plum-koala.rmq2.cloudamqp.com
Addresses:  3.218.133.71
          34.231.176.151
          44.192.12.180

PS C:\Users\LiuSean> nslookup funny-plum-koala-02.rmq2.cloudamqp.com
...

Non-authoritative answer:
Name:    funny-plum-koala-02.rmq2.cloudamqp.com
Address:  3.218.133.71

PS C:\Users\LiuSean> nslookup funny-plum-koala-03.rmq2.cloudamqp.com
...

Non-authoritative answer:
Name:    funny-plum-koala-03.rmq2.cloudamqp.com
Address:  34.231.176.151

Per Spring AMQP document https://docs.spring.io/spring-amqp/reference/html/#cluster, it seems that the preferred way is to use the individual names:

@Bean
public CachingConnectionFactory ccf() {
   CachingConnectionFactory ccf = new CachingConnectionFactory();
   ccf.setAddresses("host1:5672,host2:5672,host3:5672");
   return ccf;
}

But does this offer benefits over using the single DNS records that returns 3 addresses? I've done my share of searching but there doesn't seem to be a definitive answer.

I've tested with containers with 3 addresses and it seems to work:

ccf.setAddresses("host1:5672,host2:5672,host3:5672");

However it'll be a lot of work to set up a separate DNS server to return 3 addresses to test.


Solution

  • The CachingConnectionFactory exposes an setAddressResolver(AddressResolver) option:

    /**
     * Set an {@link AddressResolver} to use when creating connections; overrides
     * {@link #setAddresses(String)}, {@link #setHost(String)}, and {@link #setPort(int)}.
     * @param addressResolver the resolver.
     * @since 2.1.15
     */
    public void setAddressResolver(AddressResolver addressResolver) {
    

    One of the impl is probably what you are looking for:

    /**
     * {@link AddressResolver} that resolves DNS record IPs.
     * Uses {@link InetAddress} internally.
     * The first returned address is used when automatic recovery is NOT enabled
     * at the {@link ConnectionFactory} level.
     * When automatic recovery is enabled, a random address will be picked up
     * from the returned list of {@link Address}es.
     */
    public class DnsRecordIpAddressResolver implements AddressResolver {
    

    It does this internally InetAddress.getAllByName(hostName);

    From docs: https://docs.spring.io/spring-amqp/reference/html/#addressresolver