web-dev-qa-db-ja.com

Spring RabbitMQに新しいキューを作成させる方法は?

私の(限られた)rabbit-mqの経験では、まだ存在しないキューの新しいリスナーを作成すると、キューが自動的に作成されます。 Spring AMQPプロジェクトでrabbit-mqを使用してリスナーを設定しようとしていますが、代わりにエラーが発生します。これは私のxml構成です:

<rabbit:connection-factory id="rabbitConnectionFactory" Host="172.16.45.1" username="test" password="password" />

<rabbit:listener-container connection-factory="rabbitConnectionFactory"  >
    <rabbit:listener ref="testQueueListener" queue-names="test" />
</rabbit:listener-container>

<bean id="testQueueListener" class="com.levelsbeyond.rabbit.TestQueueListener"> 
</bean>

私はこれを私のRabbitMqログで取得します:

=ERROR REPORT==== 3-May-2013::23:17:24 ===
connection <0.1652.0>, channel 1 - soft error:
{amqp_error,not_found,"no queue 'test' in vhost '/'",'queue.declare'}

そして、AMQPからの同様のエラー:

2013-05-03 23:17:24,059 ERROR [org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer] (SimpleAsyncTaskExecutor-1) - Consumer received fatal exception on startup
org.springframework.amqp.rabbit.listener.FatalListenerStartupException: Cannot prepare queue for listener. Either the queue doesn't exist or the broker will not allow us to use it.

スタックトレースから、キューが「パッシブ」モードで作成されているように見えます。パッシブモードを使用せずにキューを作成する方法を誰かが指摘できるので、このエラーは表示されませんか?それとも他に何か不足していますか?

15
eric

私の問題を解決したように見えたのは、管理者を追加することでした。これが私のxmlです:

<rabbit:listener-container connection-factory="rabbitConnectionFactory"  >
    <rabbit:listener ref="orderQueueListener" queues="test.order" />
</rabbit:listener-container>

<rabbit:queue name="test.order"></rabbit:queue>

<rabbit:admin id="amqpAdmin" connection-factory="rabbitConnectionFactory"/>

<bean id="orderQueueListener" class="com.levelsbeyond.rabbit.OrderQueueListener">   
</bean>
9
eric

古いスレッドですが、これはまだGoogleでかなり高く表示されているため、新しい情報をいくつか示します。

2015-11-23

以降Spring 4.2.xwith Spring-MessagingおよびSpring-Amqp 1.4.5.RELEASEおよび Spring-Rabbit 1.4.5.RELEASEは、@ Configurationクラスにいくつかの注釈を付けることで、交換、キュー、バインディングの宣言が非常に簡単になりました。

@EnableRabbit
@Configuration
@PropertySources({
    @PropertySource("classpath:rabbitMq.properties")
})
public class RabbitMqConfig {    
    private static final Logger logger = LoggerFactory.getLogger(RabbitMqConfig.class);

    @Value("${rabbitmq.Host}")
    private String Host;

    @Value("${rabbitmq.port:5672}")
    private int port;

    @Value("${rabbitmq.username}")
    private String username;

    @Value("${rabbitmq.password}")
    private String password;

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(Host, port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);

        logger.info("Creating connection factory with: " + username + "@" + Host + ":" + port);

        return connectionFactory;
    }

    /**
     * Required for executing adminstration functions against an AMQP Broker
     */
    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
    }

    /**
     * This queue will be declared. This means it will be created if it does not exist. Once declared, you can do something
     * like the following:
     * 
     * @RabbitListener(queues = "#{@myDurableQueue}")
     * @Transactional
     * public void handleMyDurableQueueMessage(CustomDurableDto myMessage) {
     *    // Anything you want! This can also return a non-void which will queue it back in to the queue attached to @RabbitListener
     * }
     */
    @Bean
    public Queue myDurableQueue() {
        // This queue has the following properties:
        // name: my_durable
        // durable: true
        // exclusive: false
        // auto_delete: false
        return new Queue("my_durable", true, false, false);
    }

    /**
     * The following is a complete declaration of an exchange, a queue and a exchange-queue binding
     */
    @Bean
    public TopicExchange emailExchange() {
        return new TopicExchange("email", true, false);
    }

    @Bean
    public Queue inboundEmailQueue() {
        return new Queue("email_inbound", true, false, false);
    }

    @Bean
    public Binding inboundEmailExchangeBinding() {
        // Important part is the routing key -- this is just an example
        return BindingBuilder.bind(inboundEmailQueue()).to(emailExchange()).with("from.*");
    }
}

役立つソースとドキュメント:

  1. 春の注釈
  2. キュー/バインディングサポート用の宣言/構成RabbitMQ
  3. 直接交換バインディング(ルーティングキーが問題ではない場合)

:バージョンを逃したように見えます-Spring AMQP 1.5で始まり、完全に宣言できるので、物事はさらに簡単になりますリスナーですぐにバインド!

16
Jaymes Bearden

これを接続タグの後、リスナーの前に追加できますか?

<rabbit:queue name="test" auto-delete="true" durable="false" passive="false" />

残念ながら、XSDスキーマによると、(上記の)パッシブ属性は無効です。ただし、私が見たどのqueue_declare実装でも、パッシブは有効なqueue_declareパラメータでした。私はそれがうまくいくのか、彼らが将来それをサポートする予定があるのか​​を知りたいと思っています。

キュー宣言のオプションの完全なリストは次のとおりです。 http://www.rabbitmq.com/amqp-0-9-1-reference.html#class.queue

そして、これは春のウサギのスキーマの完全なXSDです(コメントが含まれています): http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd

4
Homer6

Spring Boot 2.1.6およびSpring AMQP 2.1.7以降、キューが存在しない場合は、起動時にキューを作成できます。

@Component
public class QueueConfig {

    private AmqpAdmin amqpAdmin;

    public QueueConfig(AmqpAdmin amqpAdmin) {
        this.amqpAdmin = amqpAdmin;
    }

    @PostConstruct
    public void createQueues() {
        amqpAdmin.declareQueue(new Queue("queue_one", true));
        amqpAdmin.declareQueue(new Queue("queue_two", true));
    }
}