Einfache Integration von RabbitMQ und Spring Boot

Eine Übersetzung des Artikels wurde vor Beginn des Kurses "Developer on the Spring Framework" erstellt .




Hallo alle zusammen!

Ich möchte Ihnen eine Open-Source-Bibliothek zur Verfügung stellen , die die Integration von RabbitMQ in Anwendungen auf Spring Boot erleichtert. Darüber hinaus bietet diese Bibliothek ein neues, verbessertes Konzept für Wiederholungsversuche (im Vergleich zum Standardansatz von Spring AMQP).
Vereinfacht? Aber wie?


Autokonfiguration


Angenommen, wir möchten eine Interaktion (z. B. mit SSL) mit RabbitMQ mithilfe von Spring AMQP implementieren. Wir brauchen ein paar Bohnen, wie zu schaffen ConnectionFactory, RabbitAdmin, RabbitTemplateund AbstractRabbitListenerContainerFactory.

Stellen Sie sich jedoch vor, dass es in RabbitMQ mehrere virtuelle Hosts gibt. Standardmäßig müssen Sie in Spring AMQP ein solches Ökosystem für jeden virtuellen Host mit manueller Konfiguration von RabbitTemplateund erstellen RabbitListener.



Wie Sie sehen können, nimmt all diese Konfiguration Zeit in Anspruch und kann Kopfschmerzen verursachen.

Die vorgeschlagene Bibliothek ist sich dieses Problems bewusst und konfiguriert automatisch alle diese Beans für Sie. Das einzige, was Sie tun müssen, ist die Konfiguration in zu bestimmen application.properties, und Magie wird passieren!
Wow, aber wie sieht die Konfiguration aus application.properties?

Alles ist sehr einfach. Erstens gibt es ein Präfix für die Eigenschaften - dies spring.rabbitmq.custom.

Danach müssen Sie den Namen des Ereignisses angeben. Dies ist ein sehr wichtiger Teil, da alle Einstellungen, die die Bibliothek vornimmt, auf diesem Namen basieren.

Nach dem Ereignisnamen können Sie die Eigenschaft und den Wert angeben. Alle Eigenschaften sind in der Dokumentation beschrieben .

Die Vorlage sieht also wie folgt aus: Nachfolgend finden Sie eine Beispielkonfiguration für zwei verschiedene Verbindungen.

spring.rabbitmq.custom.<YOUR_EVENT>.<PROPERTY>=<VALUE>




spring.rabbitmq.custom.some-event.host=localhost
spring.rabbitmq.custom.some-event.port=5672
spring.rabbitmq.custom.some-event.ttlRetryMessage=5000
spring.rabbitmq.custom.some-event.maxRetriesAttempts=5
spring.rabbitmq.custom.some-event.ttlMultiply=2
spring.rabbitmq.custom.some-event.queueRoutingKey=ROUTING.KEY.TEST
spring.rabbitmq.custom.some-event.exchange=ex.custom.direct
spring.rabbitmq.custom.some-event.exchangeType=direct
spring.rabbitmq.custom.some-event.queue=queue.custom.test
spring.rabbitmq.custom.some-event.autoCreate=true
spring.rabbitmq.custom.some-event.concurrentConsumers=1
spring.rabbitmq.custom.some-event.maxConcurrentConsumers=1
spring.rabbitmq.custom.some-event.virtualHost=tradeshift
spring.rabbitmq.custom.some-event.primary=true
spring.rabbitmq.custom.some-event.sslConnection=true
spring.rabbitmq.custom.some-event.tlsKeystoreLocation=file:///etc/tradeshift/your-service/tls-keystore.pkcs12
spring.rabbitmq.custom.some-event.tlsKeystorePassword=${RABBITMQ_PASS_CERT}

spring.rabbitmq.custom.another-event.host=localhost
spring.rabbitmq.custom.another-event.port=5672
spring.rabbitmq.custom.another-event.ttlRetryMessage=5000
spring.rabbitmq.custom.another-event.maxRetriesAttempts=5
spring.rabbitmq.custom.another-event.queueRoutingKey=TEST.QUEUE
spring.rabbitmq.custom.another-event.exchange=ex_test_1
spring.rabbitmq.custom.another-event.exchangeType=direct
spring.rabbitmq.custom.another-event.queue=queue_test_1
spring.rabbitmq.custom.another-event.autoCreate=true
spring.rabbitmq.custom.another-event.concurrentConsumers=1
spring.rabbitmq.custom.another-event.maxConcurrentConsumers=1
spring.rabbitmq.custom.another-event.username=guest
spring.rabbitmq.custom.another-event.password=${RABBITMQ_PASS}

Wie Sie sehen können, haben wir keine einzige Codezeile geschrieben !!!
Gut, aber Sie haben etwas über die neue Wiederholungsstrategie gesagt, oder?

Ja mein Freund sagte!

Bevor wir diese neue Strategie erläutern, werfen wir einen Blick auf das Standardverhalten von RabbitMQ und Spring AMQP.

Standardmäßig bietet RabbitMQ keine Wiederholungsverarbeitung, mit der Sie den gesamten Nachrichtenlebenszyklus steuern können.

Vor RabbitMQ 3.8 hatte der Nachrichtenkopf beispielsweise keine Eigenschaft, um die Anzahl der durchgeführten Wiederholungen zu steuern.

Standardverhalten von RabbitMQ:

  • Wenn Sie nicht definiert haben , Time-to-Live (TTL, Lebensdauer), dann wird RabbitMQ ständig versuchen , Ihre Nachricht in der Warteschlange.
  • Wenn Sie TTL definiert haben , aber dlx nicht definiert haben , wird die Nachricht nach TTL aus der Warteschlange entfernt und Sie verlieren sie.
  • Wenn Sie TTL und dlx definiert haben , wird die Nachricht nach TTL an den in dlx definierten Austauscher gesendet.


RabbitMQ-Standardverhalten

Aber was ist, wenn wir eine zunehmende TTL wollen (zum Beispiel bei instabilem Betrieb) und die Anzahl der Wiederholungsversuche kontrollieren möchten?

Gute Frage!

Es ist Zeit zu erklären, wie Spring AQMP und Spring Rabbit Tuning Library funktionieren!

Wiederholungsstrategien


Spring AMQP standardmäßig


Wenn Sie Spring AMQP standardmäßig verwenden, können Sie Wiederholungsoptionen mithilfe der folgenden Eigenschaften definieren.

Dieser Ansatz hat jedoch Probleme. Standardmäßig blockiert Spring AMQP Ihre Warteschlange, wenn Sie erneut versuchen, eine Nachricht zuzustellen.

Dieses Problem kann auf Umwegen gelöst werden: Verwenden Sie Parallelität. Auf diese Weise laden wir die JVM, und dies ist nicht der beste Ansatz. Wenn Sie fünf problematische Meldungen haben (wie im Beispiel), tritt erneut ein Engpass auf, und wir müssen die Beans im @Configuration- bin für jede Verbindung und jeden Container noch manuell ermitteln .

spring.rabbitmq.listener.simple.retry.enabled=true
spring.rabbitmq.listener.simple.retry.initial-interval=2000
spring.rabbitmq.listener.simple.retry.max-attempts=5
spring.rabbitmq.listener.simple.retry.multiplier=2
spring.rabbitmq.listener.simple.max-concurrency=5
spring.rabbitmq.listener.simple.concurrency=5


Spring RabbitMQ Tuning


Diese Bibliothek verfolgt einen anderen Ansatz mit einer separaten Warteschlange für Wiederholungsversuche. Auf diese Weise können wir TTL mithilfe des Ablaufnachrichtenparameters und des Parameters x-death steuern, um die Anzahl der Wiederholungsversuche zu steuern.
Aber wie?

Wir verwenden das dlx-Konzept in der Wiederholungswarteschlange, um die Nachricht erneut an die Hauptwarteschlange zu senden. Somit haben wir Zugriff auf den Parameter x-death und können die Lebensdauer der Nachricht programmgesteuert bestimmen.

Hinweis. Da diese Bibliothek eine Erweiterung von Spring AMQP ist, können Sie die Standard-Wiederholungsstrategie verwenden und diese Bibliothek nur für die automatische Konfiguration von Beans verwenden.


Spring RabbitMQ Tuning Retry
Kann ich Ihre Wiederholungsstrategie ohne automatische Konfiguration verwenden? Ich habe bereits viele Bohnen und ich habe keine Zeit, sie umzuschreiben.

Wir wissen, dass die Welt nicht perfekt ist, und für diese Situation haben wir ein Flag, mit dem Sie die automatische Konfiguration deaktivieren und nur unseren Ansatz für die Wiederholungsverarbeitung und andere Vorteile wie die Behälterverwaltung verwenden können.

Sie können die automatische Konfiguration mithilfe der folgenden Eigenschaft deaktivieren:

spring.rabbitmq.enable.custom.autoconfiguration=false

Aber ich habe zwei verschiedene Verbindungen. Was soll ich in diesem Fall tun?

Wenn Sie mehr als eine Verbindung haben und die automatische Konfiguration deaktivieren möchten, müssen Sie den Bean-Namen RabbitTemplatefür jede Verbindung angeben . Dies wird hier beschrieben . Sie können unsere Bean weiterhin verwenden , um die Arbeit mit Spring AMQP zu vereinfachen.

spring.rabbitmq.custom.<YOUR_EVENT>.rabbitTemplateBeanName= <RABBITTEMPLATE_BEAN_NAME>

RabbitTemplateHandler
Sehr gut! Also möchte ich das nutzen. Wie kann ich das machen? Haben Sie ein Beispiel oder eine Dokumentation?
Ja!

In diesem Repository befindet sich ein Beispielprojekt, in dem Sie sehen können, wie Sie diese Bibliothek für Herausgeber und Abonnenten verwenden.

Aber es ist so einfach, dass ich hier ein Beispiel geben werde!

Verleger


Es gibt eine Klasse in der Bibliothek RabbitTemplateHandlerund sie ist sehr einfach zu bedienen. Sie müssen die Methode aufrufen getRabbitTemplateund den virtuellen Host als Parameter übergeben, um die Bean abzurufen RabbitTemplate. Danach können Sie die convertAndSend-Methode aufrufen und in den Exchange- und Routing-Schlüsselparametern übergeben.

Hinweis : Der Austausch- und Routing-Schlüssel kann mithilfe von Anmerkungen abgerufen werdenWert.

Ein Beispiel :

@Value("${spring.rabbitmq.custom.some-event.exchange}")
private String exchangeSomeEvent;

@Value("${spring.rabbitmq.custom.some-event.queueRoutingKey}")
private String routingKeySomeEvent;

@Autowired
private final RabbitTemplateHandler rabbitTemplateHandler;

public void sendMessage(final String message) {
   rabbitTemplateHandler.getRabbitTemplate("some-event").convertAndSend(exchangeSomeEvent, routingKeySomeEvent, message);
}

Teilnehmer


Abonnenten sind auch sehr einfach. Sie müssen der Methode lediglich eine Anmerkung hinzufügen RabbitListener(standardmäßig Spring AMQP-Anmerkung) und den Namen übergeben containerFactory.
Wie finde ich den richtigen containerFactory-Namen für einen virtuellen Host heraus?

Sie müssen es nicht wissen, geben Sie einfach den Namen des Ereignisses ein und die Bibliothek wird die ganze Magie für Sie erledigen! Diese Bibliothek kann auch Wiederholungsversuche und dlq enthalten, die empfohlen werden.

Das Einschalten ist sehr einfach. Sie müssen der Methode Anmerkungen hinzufügen EnableRabbitRetryAndDlqund den Namen der Eigenschaft als Argument übergeben.

Hinweis : Sie können auch angeben, welche Ausnahmen mit Wiederholungsversuchen und dlq behandelt werden sollen. Es wird standardmäßig verarbeitet Exception.class, dh alle Ausnahmen werden behandelt.

Beispiel:

@RabbitListener(containerFactory = "some-event", queues = "${spring.rabbitmq.custom.some-event.queue}")
@EnableRabbitRetryAndDlq(event = "some-event", exceptions = { IllegalArgumentException.class, RuntimeException.class })
public void onMessage(Message message) {
   ...
}

Das ist alles! Ich hoffe, Ihnen gefällt diese Bibliothek genauso gut wie uns!

Und vor allem: Sie können gerne einen Beitrag leisten oder Feedback senden!

Besonderer Dank an


Andre Luis Gomes
Rogerio Bueno
Leonardo Ferreira



Melden Sie sich für eine kostenlose Lektion an.


All Articles