Home > Enterprise >  How to understand async vs sync in Spring AMQP?
How to understand async vs sync in Spring AMQP?

Time:09-01

I'm currently reading through Spring AMQP's official sample project along with it's corresponding explanations from Spring AMQP docs. The project involves an sync and async version, and the two only differs slightly. Here's the async version:

Producer config:

@Configuration
public class ProducerConfiguration {

  protected final String helloWorldQueueName = "hello.world.queue";

  @Bean
  public RabbitTemplate rabbitTemplate() {
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    template.setRoutingKey(this.helloWorldQueueName);

    return template;
  }

  @Bean
  public ConnectionFactory connectionFactory() {
    return new CachingConnectionFactory();
  }

  @Bean
  public ScheduledProducer scheduledProducer() {
    return new ScheduledProducer();
  }

  @Bean
  public BeanPostProcessor postProcessor() {
    return new ScheduledAnnotationBeanPostProcessor();
  }

  static class ScheduledProducer {

    @Autowired
    private volatile RabbitTemplate rabbitTemplate;

    private final AtomicInteger counter = new AtomicInteger();

    @Scheduled(fixedRate = 3000)
    public void sendMessage() {
      rabbitTemplate.convertAndSend("Hello World "   counter.incrementAndGet());
    }
  }
}

Consumer config:

@Configuration
public class ConsumerConfiguration {

  protected final String helloWorldQueueName = "hello.world.queue";

  @Bean
  public ConnectionFactory connectionFactory() {
    return new CachingConnectionFactory();
  }

  @Bean
  public SimpleMessageListenerContainer listenerContainer() {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory());
    container.setQueueNames(this.helloWorldQueueName);
    container.setMessageListener(new MessageListenerAdapter(new HelloWorldHandler()));

    return container;
  }

  @Bean
  public RabbitTemplate rabbitTemplate() {
    RabbitTemplate template = new RabbitTemplate(connectionFactory());
    template.setRoutingKey(this.helloWorldQueueName);
    template.setDefaultReceiveQueue(this.helloWorldQueueName);

    return template;
  }

  @Bean
  public Queue helloWorldQueue() {
    return new Queue(this.helloWorldQueueName);
  }
}

HelloWorldHandler:

public class HelloWorldHandler {

  public void handleMessage(String text) {
    System.out.println("Received: "   text);
  }
}

As the docs explains:

Since this sample demonstrates asynchronous message reception, the producing side is designed to continuously send messages (if it were a message-per-execution model like the synchronous version, it would not be quite so obvious that it is, in fact, a message-driven consumer). The component responsible for continuously sending messages is defined as an inner class within the ProducerConfiguration. It is configured to run every three seconds.

I failed to understand what's "async" about this code, since, from my understanding, in a basic "synchronous fashion", operations like amqpTemplate.converAndSend() and amqpTemplate.receiveAndConvert() already peforms Rabbitmq's async actions, neither producer nor consumer are blocking when sending/receiving messages.

So, how's async in this example manifested? And how to understand async vs sync in the Spring AMQP context?

CodePudding user response:

With async, the MessageListener is invoked by the framework; messages arrive whenever they are available.

With sync, the application calls a receive method which either returns immediately if no message is available, or blocks until a message arrives or a timeout expires.

In the sync case, the application controls when messages are received, with async, the framework is in control.

  • Related