Как реализовано concurrency в Spring контейнере-приемнике AMQP?

Мой контейнер XML config:

<rabbit:listener-container
        connection-factory="myConnectionFactory"
        acknowledge="none"
        concurrency="10"
        requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
</rabbit:listener-container>

и myListener - это просто класс

@Component("myListener")
public class MyListener implements MessageListener {
    @Autowired
    SomeDependency dependency;
    ....
}

Я указал concurrency="10" в своем XML. Что это означает точно?


Я нашел несколько документов. Они не так полезны:

Укажите количество одновременных пользователей для создания. Значение по умолчанию: 1.


Меня интересует, должен ли myListener быть потокобезопасным i.e.

  • Есть ли много экземпляров, созданных или один экземпляр, используемый многими потоками?
  • Можно ли получить доступ к полям экземпляра без синхронизации?
  • является SomeDependency dependency экземпляром один раз или для каждого потока/экземпляра?
  • dependency должен быть потокобезопасным?

Ответ 1

Да, чтобы использовать concurrency, ваш слушатель должен быть потокобезопасным. В контейнере есть один экземпляр прослушивателя. Тем не менее, элемент пространства <rabbit:listener-container/> namespace фактически является просто удобством для добавления "общих" атрибутов, каждый элемент-слушатель получает свой собственный контейнер.

Как правило, лучше использовать объекты без состояния (без полей, которые записываются), но это не всегда возможно.

Если ваш слушатель не является потокобезопасным, вы можете использовать...

<rabbit:listener-container
    connection-factory="myConnectionFactory"
    acknowledge="none"
    requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    ...
</rabbit:listener-container>

... и добавьте @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE). Затем вы получите контейнер для каждого слушателя, а другой экземпляр слушателя будет введен в каждый.

Вам также понадобится область прототипа для любых небезобезопасных зависимостей, введенных в слушатель.