java - Spring AMQP - 在启动时将队列注册到容器的正确方法

标签 java spring amqp spring-amqp spring-rabbit

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

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)

enter image description here

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

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

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

更新

根据加里的建议,这就是我现在的处理方式:

  @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() 中进行设置。

监听器容器默认阶段Integer.MAX_VALUE,因此容器是应用程序上下文最后启动的事物之一。

将您的 SmartLifecycle 置于较早的阶段(例如 0),以便在开始之前设置容器。

关于java - Spring AMQP - 在启动时将队列注册到容器的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57670878/

相关文章:

java - 关于Linux上Java的类路径设置

java - 从 JComboBox 获取值时出错

java - Spring 安全 405

java - 如何在 Spring Security 中创建自定义 UserDetail 对象

java - 在 Qpid Proton AMQP 1.0 客户端库中设置连接的 `max_frame_size`

java - 无法获取环境,+ java.lang.ExceptionInInitializerError,Traceback IOError : File not found -

java - 设置点击按钮时显示广告

spring - 当我设置 hbm2ddl.auto 创建时,为什么 Hibernate 会抛出 SQLGrammarException 并说表/ View 不存在?

php - 如何在 Windows 上安装 amqp

javascript - 在rabbitmq中获取路由/绑定(bind) key