如何实现Spring AMQP Listener Container中的并发性?

Par*_*bay 16 java spring amqp rabbitmq spring-amqp

我的容器XML配置:

<rabbit:listener-container
        connection-factory="myConnectionFactory"
        acknowledge="none"
        concurrency="10"
        requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
</rabbit:listener-container>
Run Code Online (Sandbox Code Playgroud)

而且myListener只是一堂课

@Component("myListener")
public class MyListener implements MessageListener {
    @Autowired
    SomeDependency dependency;
    ....
}
Run Code Online (Sandbox Code Playgroud)

concurrency="10"在我的XML中指定了.这是什么意思完全相同


我找到了一些文档.他们没有那么有用的陈述:

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


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

  • 有很多实例创建或许多线程使用单个实例?
  • 我可以访问没有同步的实例字段吗?
  • SomeDependency dependency 一次或为每个线程/实例实例化?
  • 确实dependency需要线程安全吗?

Gar*_*ell 15

是的,要使用并发性,您的侦听器必须是线程安全的.每个容器有一个侦听器实例.但是,<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>
Run Code Online (Sandbox Code Playgroud)

...并添加@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE).然后,您将为每个侦听器获取一个容器,并将为每个侦听器注入另一个侦听器实例.

对于注入侦听器的任何非线程安全依赖项,您还需要原型范围.

  • 没有; 在您的示例中,有一个具有10个使用者线程的侦听器容器; 在我的有10个容器,每个容器有一个螺纹.使用原型范围意味着每个容器都有自己的实例; 所以你的听众不需要是线程安全的.如果没有`prototype`范围,每个容器都会获得对同一实例的引用 - 实际上与原始案例没有区别(功能上).记住也要使所有下游依赖项"prototype"范围.就像我说的那样,通常最好尝试让你的监听器及其依赖关系无状态以避免这些问题. (2认同)