Als ich darüber nachdachte, über „AMQP vs HTTP“ zu schreiben, dachte ich darüber nach, über Unterschiede zwischen beiden Protokollen zu schreiben, jeden einzelnen Header zu beschreiben und warum er da ist, wie es der Fluss jeder Nachricht/jedes Pakets ist, die Sie in jedem Protokoll senden, etc. etc, etc… Aber dann wurde mir klar, dass all diese grauen Informationen da draußen sind, jeder, der etwas über das Protokoll selbst lesen möchte, kann es einfach „googlen“ und hat viele Informationen über jedes Protokoll.

Wenn Sie hier nach diesen Informationen gesucht haben, „lassen Sie mich das für Sie googeln“: AMQP, HTTP. Wenn Sie nach einem echten Anwendungsfall und einer Diskussion darüber suchen, wann und warum welche Protokolle verwendet werden sollen, dann sind Sie hier genau richtig.

Diskussionsfall

Als wir vor einiger Zeit mit der Dezentralisierung des riesigen Monolithen begannen, brauchten wir eine Möglichkeit, Daten zwischen dem Kern und den Regionen zu synchronisieren. Core ist der Name, den wir dem Ort gegeben haben, an dem sich die zentrale Datenbank und der E-Commerce-Teil befinden, und die Regionen sind Teile der Welt, in denen wir unsere Komponenten platzieren (Europa, Amerika, Asien…). Das Publish-Subscribe-Muster passte perfekt in unser Projekt, da alle Daten, die synchronisiert werden mussten, immer in eine Richtung gingen. Außerdem ermöglicht Ihnen das Muster, es umzukehren und den Abonnenten zum Herausgeber neuer Informationen zu machen und die Möglichkeit einer bidirektionalen Synchronisierung im Falle zukünftiger Anforderungen zu haben.

Damals standen wir vor der Tatsache, dass wir ein weltweites Publish-Subscribe-Muster aufbauen mussten, bei dem der Kern mit Diensten zu sprechen war, von denen wir vielleicht nicht wissen, ob sie in Betrieb sind, und das Wichtigste war, sie zu tun aufgrund des erwarteten hohen Verkehrsaufkommens zuverlässig sein (nicht nur Kern-zu-Region-Verkehr, sondern auch Verkehr, der in der Region generiert wird). Wir brauchten einen bestimmten Warteschlangenmechanismus, der die Kommunikation hält, falls die Empfänger zu beschäftigt sind, um zu antworten, aber gleichzeitig wollten wir auch den Erzeuger nicht blockieren (indem wir Anfragen immer wieder wiederholen). Wir konnten keine Kommunikation verlieren und damit überhaupt keine Synchronisierung von Daten. In diesem Moment kam uns die Idee, Messaging-Warteschlangen zu verwenden. Messaging-Warteschlangen ermöglichen Ihnen eine Middleware, die die gesamte Kommunikation beibehält, und je nachdem, wie Sie sie erstellen, können Sie die Zuverlässigkeit hinzufügen, die Sie möglicherweise benötigen, indem Sie die Bestätigung jedes Pakets erzwingen und eine Vertrauenskette in der Kommunikation verwenden.

Da waren wir also und wussten, was zu tun war, aber nicht wie. Natürlich hatte jeder von uns eine tolle Idee! Sie können immer ein sehr einfaches „Schreiben Sie irgendwo die Kommunikationen, die nicht bestätigt wurden, und versuchen Sie es später erneut, bis es funktioniert“ erstellen. Wir haben sogar versucht, Redis als Nachrichtenwarteschlange zu verwenden (und es funktioniert gut, aber es ist nicht zuverlässig). Dann fanden wir unter anderem RabbitMQ und das AMQP-Protokoll. Zuvor muss ich sagen, dass die meisten im Team diese Technologie überhaupt nicht kannten. Wir hatten keinerlei Erfahrung mit Messaging-Warteschlangen, also mussten wir viel lernen. Wir haben eine Trial-Error-Phase durchlaufen, bis wir diese Technologie in unseren Willen gezähmt haben, und der Rest ist Geschichte. Für die asynchrone interne Kommunikation verwenden wir RabbitMQ. Wir haben einen Broker pro Region plus einen im Kern und wir verwenden Schaufeln für die Übertragung von Nachrichten zwischen Kern und Regionen. Diskussion

Aber nach all den Erfahrungen, die wir in fast einem ganzen Jahr mit dieser Technologie in der Produktion mit großartiger und unbestrittener Leistung gesammelt haben, und mit den RabbitMQ-Brokern als Kern unserer Kommunikation zwischen den Komponenten, ist „AMQP vs. HTTP“ eine tägliche ( vielleicht wöchentlich) Diskussion in unserem Büro. Die Leute werden wegen dieses Themas manchmal sogar wütend aufeinander und wir führen lange sinnlose Diskussionen darüber, warum man RabbitMQ und AMQP besser verwenden sollte oder besser nicht. Zu diesem Thema (interne asynchrone Kommunikation zwischen Komponenten) gibt es vier Arten von Meinungen (die ich zumindest gefunden / gehört habe):

  • Ich bevorzuge HTTP.

  • Ich bevorzuge AMQP.

  • Ich habe keine Vorliebe für sie, ich verwende sie nur dort, wo sie bereits verwendet werden.

  • Es ist mir egal, warum ich das eine oder andere Protokoll verwende, ich möchte nur Daten synchronisieren.

Die Art der Meinungen 3 und 4 werde ich für den kommentierenden Teil dieses Artikels auslassen (wir können darüber diskutieren, wenn Sie möchten, aber es würde vom Hauptthema abweichen), also werde ich mich auf den Rest des Artikels konzentrieren auf die anderen beiden Arten von Meinungen.

Und jetzt kommt für mich der knifflige Teil dieses Artikels, denn „bevorzugen“ ist wahrscheinlich das falsche Wort. Sollten wir (als Entwickler) „Meinungen“ zu technischen Fragen haben? Oder sollten wir besser die Fakten analysieren und das jeweils Bequeme verwenden? In unserem Beruf geht es nicht um Instinkte, sondern mehr um Fakten (obwohl Instinkte auch wichtig sind!). Kommen wir also zu den Fakten:

  1. Beide Protokolle ermöglichen die Kommunikation zwischen Komponenten.

  2. Beide Protokolle sind nachvollziehbar.

  3. Beide Protokolle sind gut dokumentiert.

  4. AMQP ist asynchron.

  5. HTTP ist synchron.

  6. HTTP ist einfach zu debuggen.

  7. Die Leute sind mit HTTP vertraut.

  8. HTTP ist gut auf eine Schnittstelle abgebildet.

  9. AMQP ist einfach zu warten und einfach zu skalieren.

  10. AMQP hat eine garantierte Nachrichtenübermittlung.

  11. Bei HTTP benötigen Sie eine Art Diensterkennung.

  12. AMQP muss den Broker kennen, um die Warteschlange zum Lesen/Schreiben zu erreichen.

  13. RabbitMQ bietet Fanout-Mechanismen, Schaufeln und Föderation von Warteschlangen („out of the box“).

  14. Wenn RabbitMQ während der Verarbeitung einer Nachricht neu gestartet wird und es noch nicht fertig ist, wird es automatisch erneut in die Warteschlange gestellt und andere Backend-Dienste werden es aufnehmen und verarbeiten.

  15. HTTP wird in fast jeder Programmiersprache unterstützt.

  16. RabbitMQ (und damit AMQP) wird in mehreren Programmiersprachen unterstützt (JAVA, .NET, RUBY, Python, PHP, Objective-C, Scala, Groovy and Grails, Clojure, Jruby, Javascript, C, C++, GO, Erlang , Haskell, OCaml, Unity 3D, Perl, Common Lisp, COBOL).

Die Liste der Fakten kann mindestens ein paar Seiten lang werden, aber ich denke, dass es genug Schlüsselfakten gibt, um je nach Situation den einen oder anderen auswählen zu können.

Fakten pro HTTP

• Das Debuggen einer HTTP-Anforderung ist wirklich einfach und wiederholbar, wohingegen eine AMQP-Nachricht schwieriger zu debuggen ist (Sie benötigen eine Verbindung zur Warteschlange, Bibliotheken, möglicherweise Skripting usw.).

• HTTP ist eine vertraute Technologie für die Entwickler, sodass für einen neuen Entwickler im Projekt keine zusätzliche Schulung erforderlich ist.

• HTTP ist das am meisten unterstützte Protokoll im Internet, daher ist es eine gute Praxis, Ihre APIs als HTTP-API zu teilen.

Fakten pro AMQP

• Das Zustellen von Nachrichten mit AMQP gibt Ihnen Zuverlässigkeit, und da Sie asynchron sind, können Sie sich überhaupt keine Gedanken über die Zustellung machen.

• Es reicht aus, den Host/die IP des Clusters der AMQP-Broker zu kennen, um Nachrichten zu übermitteln/empfangen, wohingegen Sie bei HTTP je nach Region unterschiedliche Hosts und IPs haben können.

• Sie können Fanouts verwenden, was bedeutet, dass eine Nachricht ausreicht, um mehrere verschiedene Komponenten zu informieren, wodurch die Kommunikationsmenge reduziert wird.

Überlegungen zur Verwendung von AMQP

Zum Zustellen und Empfangen von AMQP-Nachrichten benötigen Sie einen Broker. Ein Broker ist nichts anderes als ein Server, der Nachrichten empfängt, speichert und zustellt. Abhängig von Ihren Kosten und Ihrer Infrastruktur kann diese Tatsache Ihr Projekt zusätzlich komplex machen, da Sie einen/mehrere/Verbund/… von Brokern konfigurieren und warten müssen.

In unserem Fall haben wir diesen Teil mit CloudAMQP ausgelagert. Dadurch mussten wir uns keine Gedanken über die Wartung machen, fügten der endgültigen Lösung jedoch zusätzliche Kosten hinzu.

Vorbemerkung

Ich würde sagen, wenn Sie mit der Welt sprechen wollen (eine API für die Nutzung durch Dritte bereitstellen), bietet HTTP alles, was Sie brauchen. Es wird unterstützt, ist bekannt und weit verbreitet. Außerdem müssen Sie sich „nicht darum kümmern“, wenn es ein Problem in der Kommunikation gibt, denn es ist die Pflicht des Clients Ihrer API, die Anfrage erneut auszuführen, wenn etwas schief gelaufen ist.

Wenn Sie eine interne Kommunikation wünschen, bei der Sie jede einzelne Anfrage kontrollieren, würde ich AMQP verwenden, da es einfach zu bedienen ist, in den meisten heutzutage verwendeten Sprachen unterstützt wird, zuverlässig, skalierbar und schnell ist.

Ich finde beide Protokolle großartig, daran besteht kein Zweifel. Aber nur einer von ihnen fügt Ihrer Kommunikation „out of the box“ Zuverlässigkeit hinzu, und das ist der Schlüssel, außerdem ist nur einer von ihnen fast sofort skalierbar und die Tatsache, dass die Kommunikation die Dienste nicht blockiert, ermöglicht es Ihnen, Ihren weiter zu nutzen Ressourcen für andere Prozesse. Warum sollte man außerdem das Rad neu erfinden und einen eigenen Zuverlässigkeitsprozess „nur so“ schaffen? Warum zusätzlichen Code hinzufügen, der gewartet werden muss, nur weil „wir es können“? Mir ist klar, wenn es asynchron ist, verwenden Sie AMQP mit RabbitMQ.

Fazit

Wahrscheinlich haben Sie schon gemerkt, dass die ganze Diskussion keinen Sinn macht, oder? Wir vergleichen hier Schuhe mit T-Shirts, und das ist ein Fehler, den wir schon lange machen.

Natürlich ist es immer gut, die gewählte Infrastruktur zu überprüfen, aber wir müssen berücksichtigen, wann und warum.