web-dev-qa-db-fra.com

Valeurs RabbitMQ AMQP.BasicProperties.Builder

Dans le RabbitMQ/AMQP Java, vous pouvez créer un AMQP.BasicProperties.Builder, Et l'utiliser pour build() une instance de AMQP.BasicProperties. Cette l'instance de propriétés construites peut ensuite être utilisée pour toutes sortes de choses importantes. Il existe de nombreuses méthodes de style "constructeur" disponibles sur cette classe de générateur:

BasicProperties.Builder propsBuilder = new BasicProperties.Builder();
propsBuilder
    .appId(???)
    .clusterId(???)
    .contentEncoding(???)
    .contentType(???)
    .correlationId(???)
    .deliveryMode(2)
    .expiration(???)
    .headers(???)
    .messageId(???)
    .priority(???)
    .replyTo(???)
    .timestamp(???)
    .type(???)
    .userId(???);

Je cherche quels champs ces méthodes de génération aident à "construire", et surtout, quelles valeurs valides existent pour chaque champ . Par exemple, qu'est-ce qu'un clusterId et quelles sont ses valeurs valides? Qu'est-ce que type et quelles sont ses valeurs valides? Etc.

J'ai passé toute la matinée à récurer:

Dans tous ces documents, je ne trouve pas de définitions claires (à part quelques vagues explications de ce que priority, contentEncoding et deliveryMode sont) de ce que chacun de ces champs sont et quelles sont leurs valeurs valides. Est-ce que quelqu'un sait? Plus important encore, quelqu'un sait-il où ces informations sont même documentées? Merci d'avance!

43
user1768830

Habituellement, j'utilise une approche très simple pour mémoriser quelque chose. Je fournirai tous les détails ci-dessous, mais voici une simple image du champ et des valeurs de BasicProperties. J'ai également essayé de mettre en évidence correctement le contexte de file d'attente/serveur et d'application.

enter image description here

Si vous voulez que je l'améliore un peu - laissez simplement un petit commentaire. Ce que je veux vraiment, c'est fournir une clé visuelle et simplifier la compréhension.

Description de haut niveau ( source 1 , source 2 ):

Veuillez noter que Clust ID est obsolète, je vais donc l'exclure.

  • ID d'application - Identifiant de l'application qui a produit le message.
    • Contexte: utilisation de l'application
    • Valeur: peut être n'importe quelle chaîne.
  • Encodage du contenu - Encodage du contenu du message
    • Contexte: utilisation de l'application
    • Valeur: encodage de contenu MIME (par exemple gzip)
  • Type de contenu - Type de contenu du message
    • Contexte: utilisation de l'application
    • Valeur: type de contenu MIME (par exemple, application/json)
  • ID de corrélation - Message corrélé à celui-ci, par ex. à quelle demande ce message est une réponse. Les applications sont encouragées à utiliser cet attribut au lieu de mettre ces informations dans la charge utile du message.
    • Contexte: utilisation de l'application
    • Valeur: toute valeur
  • Mode de livraison - Le message doit-il être conservé sur le disque?
    • Contexte: utilisation de l'implémentation de la file d'attente
    • Valeur: non persistante (1) ou persistante (2)
  • Expiration - Délai d'expiration après lequel le message sera supprimé. La valeur du champ d'expiration décrit la période TTL en millisecondes. Veuillez consulter les détails ci-dessous.
    • Contexte: utilisation de l'implémentation de la file d'attente
  • En-têtes - En-têtes de message spécifiques à l'application arbitraires.
    • Contexte: utilisation de l'application
  • ID de message - Identificateur de message sous forme de chaîne. Si les applications doivent identifier les messages, il est recommandé d'utiliser cet attribut au lieu de le placer dans la charge utile du message.
    • Contexte: utilisation de l'application
    • Valeur: toute valeur
  • Priorité - Priorité du message.
    • Contexte: utilisation de l'implémentation de la file d'attente
    • Valeurs: 0 à 9
  • ReplyTo - Nom de la file d'attente auquel les autres applications doivent envoyer la réponse. Couramment utilisé pour nommer une file d'attente de réponses (ou tout autre identifiant qui aide une application cliente à orienter sa réponse). Les applications sont encouragées à utiliser cet attribut au lieu de mettre ces informations dans la charge utile du message.
    • Contexte: utilisation de l'application
    • Valeur: toute valeur
  • Horodatage - Horodatage du moment où le message a été envoyé.
    • Contexte: utilisation de l'application
    • Valeur: secondes depuis l'époque.
  • Type - Type de message, par ex. quel type d'événement ou de commande ce message représente. Recommandé pour être utilisé par les applications au lieu d'inclure ces informations dans la charge utile du message.
    • Contexte: utilisation de l'application
    • Valeur: peut être n'importe quelle chaîne.
  • ID utilisateur - ID utilisateur facultatif. Vérifié par RabbitMQ par rapport au nom d'utilisateur de connexion réel.
    • Contexte: utilisation de l'implémentation de la file d'attente
    • Valeur: doit être un utilisateur authentifié.

BTW, j'ai finalement réussi à revoir le dernier code de serveur ( rabbitmq-server-3.1.5), il y a un exemple dans rabbit_stomp_test_util.erl:

                content_type     = <<"text/plain">>,
                content_encoding = <<"UTF-8">>,
                delivery_mode    = 2,
                priority         = 1,
                correlation_id   = <<"123">>,
                reply_to         = <<"something">>,
                expiration       = <<"my-expiration">>,
                message_id       = <<"M123">>,
                timestamp        = 123456,
                type             = <<"freshly-squeezed">>,
                user_id          = <<"joe">>,
                app_id           = <<"joe's app">>,
                headers          = [{<<"str">>, longstr, <<"foo">>},
                                    {<<"int">>, longstr, <<"123">>}]

Bon à savoir, quelqu'un veut connaître tous les détails. Parce qu'il est préférable d'utiliser des attributs de message bien connus lorsque cela est possible au lieu de placer des informations dans le corps du message. BTW, les propriétés de base des messages sont loin d'être claires et utiles. Je dirais qu'il vaut mieux en utiliser un personnalisé.

enter image description here

Bon exemple ( source )

enter image description here

Mise à jour - Champ d'expiration

Remarque importante: l'expiration appartient au contexte de la file d'attente. Le message peut donc être abandonné par les serveurs.

enter image description here

README dit ce qui suit:

expiration est un raccourci; puisque RabbitMQ s'attend à ce que ce soit une chaîne codée, nous traduisons un ttl en la représentation sous forme de chaîne de sa valeur entière.

Sources:

77
Renat Gilmanov

Au moment de la rédaction:

  1. La dernière norme AMQP est AMQP 1.0 OASIS Standard .
  2. La dernière version de RabbitMQ est 3.1.5 (serveur et client), qui prétend prendre en charge AMQP 0.9.1 (schémas pdf et XML zippés).
  3. RabbitMQ fournit sa propre description du protocole comme schéma XML y compris les extensions (c'est-à-dire non standard), plus schéma XML sans extensions (qui est identique au schéma lié via (2 )) et doc pdf .

Dans cette réponse:

  • les liens en (3) sont la principale source de détails
  • (2) pdf doc est utilisé comme détail secondaire si (3) est inadéquat
  • Le code source (client Java, serveur erlang) est utilisé comme détail tertiaire si (2) est inadéquat.
  • (1) n'est généralement pas utilisé - le protocole et le schéma ont été (assez) significativement évolués pour/par OASIS et devraient s'appliquer aux futures versions de RabbitMQ, mais ne s'appliquent pas maintenant. Les deux exceptions où (1) était utilisé étaient pour les descriptions textuelles de contentType et contentEncoding - ce qui est sûr, car ce sont des champs standard avec de bonnes descriptions dans AMQP 1.0.

Le texte suivant est paraphrasé par ces sources par moi pour être un peu plus concis ou clair.

  • content-type (AMQP XML type = "shortstr"; Java type = "String"): facultatif. Le RFC-2046 Type MIME pour la section (corps) des données d'application du message. Peut contenir un paramètre charset définissant le codage de caractères utilisé: par exemple, 'text/plain; charset = "utf-8"'. Lorsque le type de contenu est inconnu, le le type de contenu NE DEVRAIT PAS être défini, permettant au destinataire de déterminer le type réel. Lorsque la section est connue pour être des données binaires véritablement opaques, le type de contenu DEVRAIT être défini sur application/octet-stream.
  • encodage de contenu (AMQP XML type = "shortstr"; Java type = "String"): Facultatif. Lorsque présente, décrit les codages de contenu supplémentaires appliqués aux données d'application, et donc quels mécanismes de décodage doivent être appliqués afin d'obtenir le type de support référencé par le champ d'en-tête de type de contenu. Principalement utilisé pour permettre à un document d'être compressé sans perdre l'identité de son type de contenu sous-jacent. Un modificateur du type de contenu, interprété conformément à la section 3.5 de la RFC 2616. Les codages de contenu valides sont enregistrés à l'IANA. Les mises en œuvre NE DEVRAIENT PAS utiliser le codage de compression, sauf pour rester compatibles avec les messages d'origine envoyés avec d'autres protocoles, par exemple HTTP ou SMTP. Les mises en œuvre NE DEVRAIENT PAS spécifier plusieurs valeurs de codage de contenu, sauf pour être compatibles avec les messages envoyés à l'origine avec d'autres protocoles, par exemple HTTP ou SMTP.
  • en-têtes (AMQP XML type = "table"; Java type = "Map"): Facultatif. Une application- liste spécifiée des paramètres d'en-tête et de leurs valeurs. Ceux-ci peuvent être configurés pour une utilisation uniquement par l'application. En outre, il est possible de créer des files d'attente avec "Type d'échange d'en-tête" - lorsque la file d'attente est créée, une série de noms de propriétés d'en-tête match, chacun avec des valeurs facultatives à mettre en correspondance, de sorte que le routage vers cette file d'attente se fasse via la correspondance d'en-tête.
  • deliveryMode (RabbitMQ XML type = "octet"; Java type = "Integer"): 1 (non persistant) ou 2 (persistant). Ne fonctionne que pour les files d'attente qui implémentent la persistance Un message persistant est conservé en toute sécurité sur le disque et garanti d'être délivré même en cas de panne réseau grave, de panne de serveur, de débordement, etc.
  • priorité (type XML AMQP = "octet"; Java type = "Integer"): priorité relative du message ( 0 à 9 ). Un message de priorité élevée est [PEUT ÊTRE ?? - Go] envoyé avant les messages de priorité inférieure en attente dans la même file d'attente de messages. les messages doivent être supprimés afin de maintenir un niveau de qualité de service spécifique, le serveur supprimera d'abord les messages de faible priorité. Ne fonctionne que pour les files d'attente qui implémentent des priorités.
  • correlation-id (AMQP XML type = "octet"; Java type = "String"): facultatif. Pour utilisation de l'application, aucun comportement formel (RabbitMQ). Un identifiant spécifique au client qui peut être utilisé pour marquer ou identifier les messages entre les clients.
  • replyTo (AMQP XML type = "shortstr"; Java type = "String"): Facultatif. Pour l'utilisation de l'application , aucun comportement formel (RabbitMQ) mais peut contenir le nom d'une file d'attente de réponses privée, lorsqu'il est utilisé dans les messages de demande. L'adresse du nœud auquel envoyer les réponses.
  • expiration (AMQP XML type = "shortstr"; Java type = "String"): Facultatif. Schéma RabbitMQ AMQP 0.9.1 de (3) indique "Pour une utilisation d'implémentation, pas de comportement formel". Le pdf du schéma AMQP 0.9.1 de (2) indique une heure absolue à laquelle ce message est considéré comme expiré. Cependant , ces deux descriptions doivent être ignorées car ce TTL et le client/serveur indique que ce qui suit est vrai. À partir du client, l'expiration ne peut être renseignée que via l'initialisation d'application personnalisée de BasicProperties. Sur le serveur, cela est utilisé pour déterminer TTL à partir du moment où le message est reçu à le serveur, avant la mise en file d'attente. Le serveur sélectionne TTL comme minimum de (1) message TTL (client BasicProperties) expiration en tant que temps relatif en millisecondes) et (2) file d'attente TTL (configuré x-message-ttl en millisecondes) Format: chaîne entre guillemets représentant nombre de millisecondes; heure d'expiration du message reçu sur le serveur.
  • id_message (Type XML AMQP = "shortstr"; Java type = "String"): Facultatif. Pour utilisation de l'application, aucun comportement formel (RabbitMQ). S'il est défini, le producteur de messages doit lui attribuer une valeur globale unique. À l'avenir (AMQP 1.0), un courtier PEUT éliminer un message en tant que doublon si la valeur de l'identifiant du message correspond celle d'un message précédemment reçu envoyé au même noeud.
  • horodatage (type XML AMQP = "horodatage"; Java type = "Java.util.Date")): facultatif . Pour une application, aucun comportement formel (RabbitMQ). Heure absolue de création de ce message.
  • type (AMQP XML type = "shortstr"; Java type = "String"): Facultatif. Pour l'utilisation de l'application , aucun comportement formel (RabbitMQ). [Décrit le message comme étant/appartenant à un "type" ou "formulaire" ou "transaction commerciale" spécifique à une application - GB]
  • userId (AMQP XML type = "shortstr"; Java type = "String"): Facultatif. Les états du schéma XML "Pour l'utilisation de l'application, aucun comportement formel (RabbitMQ)" - mais je crois que cela a changé dans la dernière version (lire la suite). Si elle est définie, le client définit cette valeur comme identité de l'utilisateur responsable de la production du message. De - RabbitMQ : si cette propriété est définie par un éditeur, sa valeur doit être égale au nom de l'utilisateur utilisé pour ouvrir la connexion (c'est-à-dire que la validation a lieu pour s'assurer qu'il s'agit bien de l'utilisateur connecté/authentifié). Si l'utilisateur -La propriété id n'est pas définie, l'identité de l'éditeur reste privée.
  • appId (RabbitMQ XML type = "shortstr"; Java type = "String"): Facultatif. Pour l'utilisation de l'application , aucun comportement formel (RabbitMQ). L'ID de l'application de création. Peut être rempli par les producteurs et lu par les consommateurs. (En regardant le code du serveur R-MQ, ce n'est pas du tout utilisé par le serveur, bien que le plugin "webmachine-wrapper" fournit un script et des modèles correspondants pour créer une machine Web - où un administrateur peut fournir un appId au script.)
  • Identifiant du cluster (RabbitMQ XML type = "N/A"; Java type = "String"): Déconseillé dans AMQP 0.9.1 - c'est-à-dire non utilisé. Dans les versions précédentes, était l'identifiant de routage intra-cluster, destiné aux applications de cluster, qui ne devrait pas être utilisé par les applications clientes (c'est-à-dire non remplies) .Cependant, cela a été déconseillé et supprimé du schéma actuel et n'est pas utilisé par le code du serveur R-MQ.

Comme vous pouvez le voir ci-dessus, la grande majorité de ces propriétés n'ont pas de valeurs énumérées/contraintes/recommandées car elles sont "réservées à l'application" et ne sont pas utilisées par RabbitMQ. Vous avez donc un travail facile. Vous êtes libre d'écrire/lire des valeurs utiles à votre application - tant qu'elles correspondent au type de données et se compilent :). ContentType et contentEncoding sont conformes à l'utilisation HTTP standard. DeliveryMode et priority sont des nombres contraints.

Remarque: des constantes utiles mais simples pour AMQP.BasicProperties sont disponibles dans la classe MessageProperties .

À votre santé :)

MISE À JOUR AU POST:

Avec un grand merci à Renat (voir les commentaires), nous avons examiné le code du serveur erlang dans rabbit_amqqueue_process.erl et la documentation sur RabbitMQ TTL Extensions to AMQP . Expiration du message (time- à vivre) peut être spécifié

  • par file d'attente via:

    Map<String, Object> args = new HashMap<String, Object>();
    args.put("x-message-ttl", 60000);
    channel.queueDeclare("myqueue", false, false, false, args);
    
  • ou par message via:

    byte[] messageBodyBytes = "Hello, world!".getBytes();
    AMQP.BasicProperties properties = new AMQP.BasicProperties();
    properties.setExpiration("60000");
    channel.basicPublish("my-exchange", "routing-key", properties, messageBodyBytes);
    

Ici, le ttl/expiration est en millisecondes, donc 60 sec dans chaque cas. Avoir mis à jour la définition ci-dessus de expiration pour refléter cela.

10
Glen Best

La spécification AMQP définit un modèle générique et extensible pour les propriétés.

Les propriétés AMQP sont quelque peu similaires dans leur concept aux en-têtes HTTP, en ce qu'elles représentent des métadonnées sur les messages en question. Tout comme en HTTP, ils sont encadrés séparément à la charge utile du message. Mais ils sont fondamentalement une carte clé/valeur.

Certains courtiers comme RabbitMQ interpréteront certaines propriétés de message comme expiration pour ajouter une valeur spécifique au fournisseur supplémentaire (dans ce cas, application d'un TTL ).

Mais au final, les propriétés AMQP ne sont qu'un gros tas de paires clé/valeur qui sont envoyées en toute sécurité avec chaque message, si vous choisissez de le faire. La documentation de votre courtier AMQP vous dira lesquels ils interprètent spécialement et comment envoyer les vôtres.

Cela étant dit, si vous posez cette question en premier lieu, vous n'avez probablement pas besoin de vous en préoccuper. Vous pourrez envoyer des messages avec succès sans avoir à vous soucier de définir des propriétés de message.

0
Brian Kelly