如何在春季 AMQP 侦听器容器中实现并发?

2022-09-03 02:21:42

我的容器 XML 配置:

<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;
    ....
}

我已经在我的XML中指定了。这到底是什么意思?concurrency="10"


我找到了一些文档。他们没有那么有帮助,说明:

指定要创建的并发使用者数。默认值为 1。


我感兴趣的是是否必须是线程安全的,即MyListener

  • 是否创建了许多实例或许多线程使用了单个实例?
  • 是否可以在没有同步的情况下访问实例字段?
  • 是实例化一次还是针对每个线程/实例?SomeDependency dependency
  • 是否需要线程安全?dependency

答案 1

是的,要使用并发性,您的侦听器必须是线程安全的。每个容器有一个侦听器实例。但是,命名空间元素实际上只是添加“共享”属性的便利,每个侦听器元素都有自己的容器。<rabbit:listener-container/>

通常最好使用无状态对象(没有写入的字段),但这并不总是可能的。

如果您的侦听器不是线程安全的,则可以使用...

<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)

您还需要为注入侦听器的任何非线程安全依赖项提供原型作用域。


答案 2

推荐