पाठ 22 / 25

Client Best Practices

Manage connections, channels and recovery correctly in client applications.

Long-lived connections, careful channels

Most RabbitMQ problems in production come from client code. Connections are expensive: open one (or a few) per process and keep it for the life of the application, never one per message or per HTTP request. Channels are cheap but not free; in most client libraries a channel must not be shared between threads, so use a channel per thread or a pool, and use separate channels (or connections) for publishing and consuming so publisher flow control does not stall consumers. Enable automatic connection recovery (built into the Java and .NET clients; implemented with reconnect loops in others) and make topology declarations idempotent so they can be replayed after reconnects. Set heartbeats so dead TCP connections are detected. In Spring, Spring AMQP provides RabbitTemplate with confirms and returns, and @RabbitListener with configurable acknowledgement, prefetch, concurrency and retry with dead-lettering. Name connections (a client property) so they are identifiable in the management UI.

One connection, several channels

A process keeps one long-lived connection and opens channels for publishing and consuming.

A thick pipe between an application box and a broker box, with several thinner coloured lines running inside it.
Figure 8.1 — Multiplexing channels over a long-lived connection.

A Spring AMQP listener with manual concerns configured

Prefetch, concurrency and dead-lettering on rejection come from configuration.

@Configuration
class RabbitConfig {
    @Bean
    SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory cf) {
        var f = new SimpleRabbitListenerContainerFactory();
        f.setConnectionFactory(cf);
        f.setPrefetchCount(20);
        f.setConcurrentConsumers(4);
        f.setMaxConcurrentConsumers(8);
        f.setDefaultRequeueRejected(false);      // failures go to the DLX, not back to the queue
        return f;
    }
}

@Component
class BillingListener {
    @RabbitListener(queues = "billing.orders")
    void onOrderPlaced(OrderPlaced event) {
        invoices.createFor(event);              // exception -> rejected -> dead-lettered
    }
}

Never open a connection per message

A web handler that connects, publishes and disconnects for every request can overwhelm the broker with connection churn and TLS handshakes. Create the connection at start-up and reuse it.

त्वरित जाँच: Which practice is recommended for RabbitMQ client connections?

  • Open a new connection for every message
  • Share one channel across all threads
  • Keep a long-lived connection per process and use channels for operations
  • Disable heartbeats
Answer

Keep a long-lived connection per process and use channels for operations — Long-lived connections with appropriately scoped channels avoid churn and thread-safety problems.