web-dev-qa-db-fra.com

Comment obtenir Spring RabbitMQ pour créer une nouvelle file d'attente?

Dans mon expérience (limitée) avec rabbit-mq, ​​si vous créez un nouvel écouteur pour une file d'attente qui n'existe pas encore, la file d'attente est automatiquement créée. J'essaie d'utiliser le projet Spring AMQP avec rabbit-mq pour configurer un écouteur, et j'obtiens une erreur à la place. Voici ma configuration 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>

J'obtiens ceci dans mes journaux 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'}

Et une erreur similaire d'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.

Il semblerait d'après la trace de la pile que la file d'attente est créée en mode "passif" - Quelqu'un peut-il indiquer comment je créerais la file d'attente sans utiliser le mode passif, donc je ne vois pas cette erreur? Ou est-ce que je manque autre chose?

15
eric

Ce qui semblait résoudre mon problème était l'ajout d'un administrateur. Voici mon 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

Fil plus ancien, mais cela apparaît toujours assez haut sur Google, alors voici quelques informations plus récentes:

2015-11-23

Depuis Spring 4.2.x avec Spring-Messaging et Spring-Amqp 1.4.5.RELEASE et Spring-Rabbit 1.4.5.RELEASE , déclarer les échanges, les files d'attente et les liaisons est devenu très simple grâce à une classe @Configuration quelques annotations:

@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.*");
    }
}

Quelques sources et documentation pour vous aider:

  1. annotations de printemps
  2. Déclaration/configuration de RabbitMQ pour le support de file d'attente/liaison
  3. Liaison d'échange directe (lorsque la clé de routage n'a pas d'importance)

Remarque : Il semble que j'aie manqué une version - en commençant par Spring AMQP 1.5 , les choses deviennent encore plus faciles car vous pouvez déclarer la liaison complète directement à l'auditeur!

16
Jaymes Bearden

Pouvez-vous ajouter ceci après votre balise de connexion, mais avant l'auditeur:

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

Malheureusement, selon le schéma XSD, l'attribut passif (répertorié ci-dessus) n'est pas valide. Cependant, dans chaque implémentation queue_declare que j'ai vue, passive a été un paramètre queue_declare valide. Je suis curieux de voir si cela fonctionnera ou s'ils prévoient de l'appuyer à l'avenir.

Voici la liste complète des options pour une déclaration de file d'attente: http://www.rabbitmq.com/amqp-0-9-1-reference.html#class.queue

Et voici le XSD complet pour le schéma du lapin de printemps (avec commentaires inclus): http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd

4
Homer6

Depuis Spring Boot 2.1.6 et Spring AMQP 2.1.7 vous pouvez créer des files d'attente au démarrage si elles n'existent pas avec ceci:

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