Spring AMQP-在启动时将队列注册到容器的正确方法 [英] Spring AMQP - Proper way to register queues to container on startup

查看:85
本文介绍了Spring AMQP-在启动时将队列注册到容器的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一种情况,我需要在运行时动态地将队列注册到 SimpleMessageListenerContainer .我遇到的问题是由于以下原因而发生的死锁:

I have a situation where I need to register queues dynamically in a run-time to a SimpleMessageListenerContainer. The problem I am experiencing is a deadlock that happens because of this:

Thread: [52] Thread1 wants the lock java.lang.Object@5537e0df
org.springframework.amqp.rabbit.connection.CachingConnectionFactory.getDeferredCloseExecutor(CachingConnectionFactory.java:907)
org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.restart(SimpleMessageListenerContainer.java:739)


Thread: [183] Thread2 wants the lock java.lang.Object@556fa9d6
org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.queuesChanged(SimpleMessageListenerContainer.java:689)
org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:634)
org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createBareChannel(CachingConnectionFactory.java:578)

这是有问题的代码-在这里,我尝试在 connectionListener onCreate 回调中设置客户端队列.

and this is the code that is problematic - here I try to setup client queues in onCreate callback in connectionListener.

connectionFactory
        .addConnectionListener(
            new ConnectionListener() {
              @Override
              public void onCreate(Connection connection) {
                setupClientQueues(); ----> will call container.setQueueNames which will result in calling queuesChanged
              }

              @Override
              public void onClose(Connection connection) {
                // nothing to do
              }
            });

是否存在一些标准(正确)的方法来轻松地动态注册和创建队列而不会导致死锁?

Is there some standard (proper) way to easily register and create queues dynamically without causing this deadlock?

更新

在Garry建议之后,这就是我现在的处理方式:

This is how I handle it now, after Garry suggestion:

  @Bean
  public SmartLifecycle containerQueueSetter(){
    return new SmartLifecycle(){
      private boolean running;

      @Override
      public int getPhase() {
        return 0;
      }

      @Override
      public void start() {
        //CREATE QUEUES HERE - since I create and register them as beans,
        //it will work even when rabbit is reconnected
        //REGISTER QUEUES TO SIMPLE_MESSAGE_LISTENER_CONTAINER
        running = true;
      }

      @Override
      public void stop() {
        log.info("Stopping dynamic queue registerer.");
        running = false;
      }

      @Override
      public boolean isRunning() {
        return running;
      }

      @Override
      public boolean isAutoStartup() {
        return true;
      }

      @Override
      public void stop(Runnable callback) {
        stop();
        callback.run();
      }
    };
  }

推荐答案

最好实现 SmartLifecycle 并在 start()中进行设置.

It's better to implement SmartLifecycle and do the setup in start().

侦听器容器的默认 phase Integer.MAX_VALUE ,因此这些容器属于应用程序上下文启动的最后事物.

The listener container default phase is Integer.MAX_VALUE so the containers are amongst the last things started by the application context.

将您的 SmartLifecycle 放在较早的阶段(例如0),以便在启动容器之前先进行设置.

Put your SmartLifecycle in an earlier phase (e.g. 0) so the containers will be set up before starting.

这篇关于Spring AMQP-在启动时将队列注册到容器的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆