web-dev-qa-db-fra.com

Pourquoi mes chaînes RabbitMQ continuent-elles à fermer?

Je débogue du code Java qui utilise Apache POI pour extraire des données de documents Microsoft Office. Parfois, il rencontre un document volumineux et le POI se bloque lorsqu'il manque de mémoire. À ce stade, il tente de publier l'erreur sur RabbitMQ, afin que les autres composants puissent savoir que cette étape a échoué et entreprendre les actions appropriées. Cependant, lorsqu'il tente de publier dans la file d'attente, il reçoit un com.rabbitmq.client.AlreadyClosedException (clean connection shutdown; reason: Attempt to use closed channel).

Voici le code du gestionnaire d'erreurs: 

try {
    //Extraction and indexing code
}
catch(Throwable t) {
    // Something went wrong! We'll publish the error and then move on with
    // our lives
    System.out.println("Error received when indexing message: ");
    t.printStackTrace();
    System.out.println();
    String error = PrintExc.format(t);
    message.put("error", error);

    if(mime == null) {
        mime = "application/vnd.unknown";
    }

    message.put("mime", mime);
    publish("IndexFailure", "", MessageProperties.PERSISTENT_BASIC, message);
}

Pour être complet, voici la méthode de publication:

private void publish(String exch, String route, 
    AMQP.BasicProperties props, Map<String, Object> message) throws Exception{
    chan.basicPublish(exch, route, props, 
        JSONValue.toJSONString(message).getBytes());  
}

Je ne trouve aucun code dans le bloc try qui semble fermer le canal RabbitMQ. Existe-t-il des circonstances dans lesquelles le canal pourrait être fermé implicitement?

EDIT: Je devrais noter que l'exception BeenClosedException est levée par l'appel basicPublish dans la publication.

24
quanticle

Un canal AMQP est fermé en cas d'erreur de canal. Deux choses courantes pouvant causer une erreur de canal:

  • Essayer de publier un message sur un échange qui n'existe pas
  • Essayer de publier un message avec le jeu d'indicateurs immédiat qui n'a pas de file d'attente avec un jeu de consommateurs actif

J'examinerais la possibilité de configurer ShutdownListener sur le canal que vous essayez d'utiliser pour publier un message à l'aide de addShutdownListener () afin de saisir l'événement d'arrêt et de voir la cause.

35
alanxz

Une autre raison dans mon cas était que, par erreur, j'ai accusé réception d'un message à deux reprises. Cela entraînait des erreurs RabbitMQ dans le journal comme après le deuxième accusé de réception. 

=ERROR REPORT==== 11-Dec-2012::09:48:29 ===
connection <0.6792.0>, channel 1 - error:
{amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}

Après avoir supprimé l'accusé de réception en double, les erreurs sont disparues et le canal ne s'est plus fermé, de même que l'exception BeenClosedException. 

11
Christoph

J'aimerais ajouter cette information aux autres utilisateurs recherchant ce sujet.

Une autre raison possible pour la réception d'une exception de canal fermé est lorsque les éditeurs et les consommateurs accèdent au canal/à la file d'attente avec une déclaration/des paramètres de file d'attente différents

Éditeur

channel.queueDeclare("task_queue", durable, false, false, null);

Ouvrier

channel.queueDeclare("task_queue", false, false, false, null);

À partir du site RabbitMQ

RabbitMQ doesn't allow you to redefine an existing queue with different parameters and will return an error to any program that tries to do that
4
denil

J'ai aussi eu ce problème. La raison de mon cas est que, tout d’abord, j’ai construit la file d’attente avec durable = false et que, dans le fichier journal, ce message d’erreur apparaît lorsque je suis passé à durable:

"argument inégal 'durable' pour la file d'attente 'logsQueue' dans vhost '/': reçu' vrai 'mais actuel est' faux '"

Ensuite, j'ai changé le nom de la file d'attente et cela a fonctionné pour moi. J'ai supposé que le serveur RabbitMQ conserve quelque part l'enregistrement des files d'attente créées et qu'il ne peut pas changer le statut de durable à non durable et vice versa.

Encore une fois j'ai fait durable = false pour la nouvelle file d'attente et cette fois j'ai eu cette erreur

"argument inégal 'durable' pour la file d'attente 'logsQueue1' dans vhost '/': reçu' false 'mais current est' true '"

Mon hypothèse était vraie. Quand j'ai listé les files d'attente sur le serveur rabbitMQ par:

rabbitmqctl list_queues 

J'ai vu les deux files d'attente sur le serveur.

Pour résumer, 2 solutions sont: 1. renommer le nom de la file d'attente, ce qui n'est pas une bonne solution 2. réinitialiser rabbitMQ par:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
0
M. Mashaye

Pour ceux qui se demandent pourquoi leurs canaux de consommation se ferment, vérifiez si vous essayez d'acquitter ou d'empiler une livraison plus d'une fois.

Dans le journal rabbitmq, vous verrez des messages tels que:

l'opération basic.ack a provoqué une exception de canal precondition_failed: étiquette de livraison inconnue ...

0
la0rg