Asynchrone Verarbeitung durch Message Queues: Was ist das und wofür ist das gut?
In vielen Applikationen gibt es Bereiche, die einfach etwas Zeit für die Verarbeitung brauchen, aber das klassische Anfrage/Antwort (Request/Response) Verhalten nicht blockieren sollen. Oft werden dafür asynchrone Prozesse verwendet. Durch den Einsatz von Message Queues ergeben sich weitere Vorteile wie u.a. granulare Skalierbarkeit und Unabhängigkeit von einzelnen Programmiersprachen. RabbitMQ ist einer der Platzhirsche im Bereich Open-Source-Message-Broker.
In dieser Episode klären wir wofür Message Queues gut sind, bei welchen klassischen Anwendungsfällen diese helfen können, welche Herausforderungen diese Darstellen, wo der Unterschied zu Pub/Sub oder Streams ist und was Redis, Kafka und ZeroMQ damit zu tun hat.
Bonus: Warum Software rostet.
Links
- RabbitMQ: https://www.rabbitmq.com/
- ActiveMQ: https://activemq.apache.org/
- AMQP: https://www.amqp.org/
- Jakarta Messaging: https://de.wikipedia.org/wiki/Jakarta_Messaging
- Red Hat / JBoss AMQ: https://www.redhat.com/de/technologies/jboss-middleware/amq
- Apache Kafka: https://kafka.apache.org/
- ZeroMQ: https://zeromq.org/
- Erlang mnesia: https://www.erlang.org/doc/man/mnesia.html
Sprungmarken
Hosts
- Wolfgang Gassler (https://mastodon.social/@woolf)
- Andy Grunwald (https://twitter.com/andygrunwald)
Feedback (gerne auch als Voice Message)
- Email: stehtisch@engineeringkiosk.dev
- Mastodon: https://podcasts.social/@engkiosk
- Twitter: https://twitter.com/EngKiosk
- WhatsApp +49 15678 136776
Transkript
Andy Grunwald (00:00:04 - 00:00:51)
Herzlich willkommen zu einer neuen Episode vom Engineering Kiosk. Heute geht es um das Thema Message Queues, also die asynchrone Verarbeitung von Nachrichten durch dedizierte Worker oder auch Consumer genannt. Wir klären, was Message Queues sind und welche klassischen Anwendungsfälle damit abgedeckt werden können, was der Open Source Platzhirsch RabbitMQ als Message Broker so drauf hat, ob eine relationale Datenbank auch als Message Queue genutzt werden kann, wo der Unterschied zu PubSub und Streams ist und was Redis, Kafka und ZeroMQ damit zu tun haben. Und los geht's! Viel Spaß! Lieber Wolfgang, ein frohes neues Jahr. Mich würde mal interessieren, wann standest du das letzte Mal in einer Warteschlange? Wann musstest du mit einer Reihe von Leuten auf etwas warten?
Wolfi Gassler (00:00:52 - 00:01:04)
Da, wo ich am meisten warte in letzter Zeit, ist bei der Post, wenn ich irgend so ein dummes Paket, das ich nicht in so einem Automaten abgeben kann, wirklich eine Person überreichen muss zum Zurücksenden von irgendeinem Online-Versand. Und ich ärgere mich jedes Mal wieder.
Andy Grunwald (00:01:04 - 00:01:11)
Also hier in Deutschland kann man dem Paketboten, wenn der kommt, auch die Retouren wieder mitgeben. Geht das bei euch nicht?
Wolfi Gassler (00:01:12 - 00:01:17)
Das geht nur bei dir am Land, weil du den persönlich kennst und der noch bei der Feuerwehr ist und ein Kollege aus dem Dorf.
Andy Grunwald (00:01:17 - 00:01:51)
Nee, das ist ein offizieller Service der Deutschen Post, aber ich gebe auch zu, hier bei mir in den Dörfern haben wir nicht so eine Packstation. Das bedeutet, das, was du da sagst, das kenne ich halt auch, dass man noch zu so einer Postfiliale fahren muss und so weiter, aber die Tage hat mich mein Paketbote angesprochen und sagte, immer die ganzen Sachen, die ich euch zustelle, so Kleidung, so passt die euch immer alles? Ich sag so, Wieso sollte die uns immer passen? Natürlich passt sie uns nicht. Ja, ihr gebt nie was bei mir zurück und das machen aber alle hier im Dorf. Und da habe ich dann erst gelernt, ich kann dem Paketboten auch Retouren zurückgeben.
Wolfi Gassler (00:01:51 - 00:01:57)
Ja, du siehst denn ja, ich sehe den gar nie. Der wirft das Paket irgendwo immer hin in eine Ecke und ist dann wieder weg.
Andy Grunwald (00:02:02 - 00:02:11)
Also oft sehe ich den nicht, weil bei mir wird auch immer alles vor die Haustür gelegt und dann kann ich aber auch einfach nur Pakete da hinlegen und sage einfach bitte mitnehmen und dann wird das auch einfach mitgenommen.
Andy Grunwald (00:02:13 - 00:02:17)
Hast du denn am Paketboden auch eine kleine Freude zu Weihnachten gemacht?
Andy Grunwald (00:02:20 - 00:02:27)
Vielleicht ist das genau der Unterschied. Ich habe nämlich eine kleine Merci-Schokoladentafel für meinen Paketboten gekauft, weil der immer so nett ist.
Wolfi Gassler (00:02:27 - 00:02:32)
Moment, dein Paketbote bekommt eine Merci-Schokolade, eben noch nie eine Merci-Schokolade von dir bekommen.
Andy Grunwald (00:02:38 - 00:02:45)
Zurück zum Thema Warteschlangen. Ich war vor kurzem mal wieder in einem Restaurant in Düsseldorf, und zwar im japanischen Viertel.
Wolfi Gassler (00:02:45 - 00:02:47)
Da sind wirklich immer viele Schlangen, kann ich mich noch gut erinnern.
Andy Grunwald (00:02:48 - 00:03:40)
Und dann stand ich vor einem koreanischen Restaurant im japanischen Viertel, das muss man sich auf der Zunge zergehen lassen, und hatte auch sogar Tisch reserviert. Also ich komme da an und meine Frau schon, ach du meine Güte, müssen wir uns jetzt hier anstehen? Ein Moment, mal kurz die Schlange gefragt, habt ihr reserviert? Nein, ich einfach vorne durchgegangen und stand dann ganz vorne, weil ich reserviert hatte. Und dann habe ich mich gefragt, dann hat die Dame vom Restaurant gesagt, okay, warten Sie mal bitte noch ein paar Minuten, ist gerade noch kein Tisch frei, aber wir haben Ihre Reservierung hier stehen. Und auf jeden Fall habe ich mich dann gefragt, okay, wie händeln das eigentlich Restaurants, beziehungsweise Restaurantbetreiber, dass, wenn das Ding konstant voll ist, dass dann immer zu der reservierten Zeit ein Tisch frei ist, ohne großen Ausfall, nenne ich mal, zu haben. Beispiel, man hat für 20 Uhr reserviert und um 19.30 Uhr zahlt wer. Die halten ja nicht eine halbe Stunde den Tisch vor, oder?
Wolfi Gassler (00:03:40 - 00:04:02)
Mir fällt gerade auf, das wäre eigentlich eine ideale, coole Frage für Interviews, für Tech-Interviews. Wie würde man sowas programmieren und realisieren, um das möglichst effizient abzubilden? Was würdest du für eine Technologie verwenden, Andi, dafür? Das ist immer die beste Frage, die Technologie davor zu klären, bevor man eigentlich das Problem und den Algorithmus definiert hat, setzt man sich schon mal fest auf was für Technologie.
Andy Grunwald (00:04:03 - 00:04:31)
Ich glaube, ich würde mir ziemlich viele Daten besorgen, wie lang ein Essen in der Küche braucht, um fertig zu werden und dann die Zeiten, indem man die Zwischensteps messen. Okay, Essen ist ausgeliefert, Essen ist gegessen, Teller wurde wieder abgeholt und so weiter. Weil dann kann man, glaube ich, relativ gut abschätzen. Ach so, und das dann noch korrelieren mit der Gruppengröße. Also sitzen da zwei Leute, sitzen da vier Leute und so weiter und so fort. Und dann über Zeit so Estimations machen.
Wolfi Gassler (00:04:31 - 00:04:44)
Also du würdest Process Mining machen. Du bist schon in einer hippen Industrie jetzt unterwegs. So von den neuen, coolen, milliardenbewerteten Startups wie Celonis und so weiter. Business Process Mining.
Andy Grunwald (00:04:44 - 00:05:04)
Ich wusste nicht, dass man das Process Mining nennt, aber die nächste Frage wäre, wie würde man das from the get-go, also bei einem neuen Restaurant machen? Weil das Process Mining, wenn du es so nennst, basiert ja auf den Daten und die sammelt man ja nur über Zeit und wenn alle Leute, die die reservieren, immer eine halbe Stunde warten, dann kommen die Gäste ja nicht, dann erreiche ich die Zeit für die Datensammlung ja gar nicht.
Wolfi Gassler (00:05:07 - 00:05:27)
Eine AI. Keine AI, sondern nur eine AI, eine Intelligence. Du holst dir einfach eine Person, die das schon mal gemacht hat und diese Better Recognition schon drauf hat und einfach weiß, wie so ein Restaurant funktioniert. Da sieht man wieder dieses Over-Engineering von Technikern. Die ganzen Restaurantbesitzer haben das einfach intus, wahrscheinlich, wie das funktioniert. Das ist total easy.
Andy Grunwald (00:05:27 - 00:05:34)
Kommen wir zurück zu meiner Warteschlange. Wir mussten dann auch nicht lange stehen, hatten dann, dank der Reservierung, einen relativ schnellen Tisch.
Wolfi Gassler (00:05:35 - 00:05:38)
Und dank einer AI, die die haben, einer Intelligence, die das übernimmt.
Andy Grunwald (00:05:38 - 00:05:49)
Ja, da waren mehrere intelligente Leute auf jeden Fall. Die hatten, die waren auf jeden Fall auf Zack, würde man sagen. Da war ich halt schon ein bisschen beeindruckt, wie das ganze Queuing da so funktioniert.
Wolfi Gassler (00:05:49 - 00:05:55)
Und jetzt kommt diese Traumüberleitung von dir zu Queuing im IT-Sektor.
Wolfi Gassler (00:05:59 - 00:06:08)
Du bist der Meister der Überleitungen. Darf ich dir das mal sagen? Du wirst eine Messie-Schachtel von mir bekommen als Dankeschön für diese Überleitungen.
Andy Grunwald (00:06:08 - 00:06:20)
Bevor wir ins Thema einsteigen, eine finale Frage. Wenn du so eine Messie-Packung hast, ist das auch so, dass du manche Sachen isst, die zum Beispiel mit Nuss, aber die dann mit Marzipan liegen lässt? Oder bist du so ein Typ, der alle Messie-Geschmäcker...
Andy Grunwald (00:06:21 - 00:06:25)
Ja, aber du lässt dann auch bestimmte Messie-Farben liegen, oder?
Andy Grunwald (00:06:31 - 00:06:43)
Ich wusste nicht, dass dieser Tag kommt. Wir haben eine Gemeinsamkeit. Wolfgang, ich habe gedacht, wir bleiben seit Jahr und Tag auf diesem Kaiserschmarrn mit oder ohne Rosinen stecken, aber bei Messi haben wir uns getroffen. Ernsthaft?
Wolfi Gassler (00:06:43 - 00:06:47)
Ja, aber das ist doch bei jeder Person so, oder? Grün ist immer das Beste.
Andy Grunwald (00:06:47 - 00:06:56)
Ja, ich frage mich halt, gibt es Personen auf dieser Welt... Ja, die mit einer Nuss-Allergie. Ja, aber die lassen ja da Nuss liegen. Ich frage mich ja, gibt es Personen auf dieser Welt, die alle Messy-Farben mögen?
Andy Grunwald (00:06:59 - 00:07:23)
Kommen wir zurück zum Thema Message-Queuing. Heute geht es mal ein bisschen um Message-Queuing und wir steigen mal ein bisschen das Thema ein. Was ist Message-Queuing? Warum braucht man das? Was sind typische Anwendungsfälle? aber auch was gibt es denn da für Tools auf dem Markt beziehungsweise wir schauen uns ein ganz spezielles an und zwar RabbitMQ und wir versuchen mal so ein bisschen Licht ins Dunkle der Warteschlange zu bringen.
Wolfi Gassler (00:07:23 - 00:07:40)
Dann erleuchte mich mal und erklär mir was Message Queues sind und vielleicht noch besser für was brauche ich Message Queues? Also in was für einem Anwendungsfall würdest du sagen, wenn jetzt wieder klassische Interviewfrage für das Restaurant zum Beispiel, wo braucht man Message Queues? Was ist der klassische Anwendungsfall?
Andy Grunwald (00:07:40 - 00:07:59)
Message Queues sind generell erstmal eine Subkomponente oder ein Subsystem deiner größeren Anwendung und im generellen geht es eigentlich darum, dass alle Anwendungsfälle, die asynchron behandelt werden können, abgebildet werden können. Hä, boah, jetzt hör doch mal auf da mit diesen Fachbegriffen blablabla, bleib mal praktisch.
Andy Grunwald (00:08:03 - 00:08:20)
Der optimalste Anwendungsfall ist eigentlich mal so ein Newsletter-Versand oder ein E-Mail-Versand. Es gibt ja nichts Asynchroneres als E-Mail. Die versende ich jetzt und bei E-Mails ist es ja nicht wichtig, ob die in einer Sekunde, fünf Sekunden oder 60 Sekunden ankommt. Deswegen kann sowas perfekt asynchron gemacht werden.
Wolfi Gassler (00:08:20 - 00:08:31)
Okay, nehmen wir mal an, ich weiß noch nicht, dass Newsletter das neue, hippe Werbetool eigentlich schlechthin ist und ich bin auch der alten Meinung, dass kein Mensch mehr E-Mails liest. Gibt es irgendwelche anderen Anwendungsfälle, die ganz klassisch sind?
Andy Grunwald (00:08:31 - 00:08:39)
Zum Beispiel Bildverarbeitung. Wenn du jetzt irgendwo dein Bild hochlädst, Beispiel du hast dich bei einem neuen sozialen Netzwerk angemeldet.
Andy Grunwald (00:08:40 - 00:09:57)
Zum Beispiel. Und du lädst dein Avatar hoch, ein Gesicht von dir. In der Regel nehmen sich diese Services dein Bild, 2000 x 2000 und 10 MB groß, schmeißen das in eine Warteschlange und rechnen dieses Bild dann in verschiedene Größen und weboptimiert runter und legen das dann irgendwo ab, um einfach nur Traffic zu sparen, wenn jemand auf dein Profil geht, um dein Avatar zu gucken. Das ist zum Beispiel ein perfekter Use Case für asynchrone Verarbeitung, denn dein Bild wird hochgeladen, irgendwo hingespeichert, dann wird eine Nachricht in eine Warteschlange gepackt und dann wird dein Bild in verschiedene Formate und Größen konvertiert. Und das kann, das muss ja nicht on the fly passieren, das kann ja auch ein paar Sekunden brauchen. Und in der Zeit, wo das noch nicht verarbeitet ist, stellen die halt das Originalbild auf der Webseite dar. Und wenn das neue dann fertig ist, dann nehmen sie die kleineren Größe. Das ist so einer der Anwendungsfelder. Ein anderer ist zum Beispiel Log Processing. Dein Webserver oder deine Applikation generiert eine ganze Menge Logs. Wann, wie, wo, welcher User worauf zugegriffen hat. Diese Logs irgendwo zu speichern, zu analysieren, Summen darüber zu bilden, wie viele User haben diese Webseite aufgerufen und so weiter und so fort. Sowas kann man ja im Backend oder Zeit unabhängig machen. Also da ist es in der Regel nicht systemkritisch, ob die Daten eine Sekunde oder drei Sekunden später kommen.
Wolfi Gassler (00:09:57 - 00:10:25)
Das heißt eigentlich geht es darum, wenn ich große Datenmengen in irgendeiner Form verarbeiten will und die Verarbeitung braucht Zeit, so dass ich es nicht real-time machen kann und dass es auch nicht kritisch ist. Also wenn ich irgendeine Zeile in eine Datenbank einfüge, dann geht das erstens mal relativ schnell üblicherweise und es ist kritisch, dass ich die Antwort abwarten muss. Aber wenn ich asynchron irgendwas abarbeiten kann, was länger dauert, dann ist Message Queues eine gute Technologie dafür. Seht es richtig.
Andy Grunwald (00:10:25 - 00:10:48)
Ja, ich würde es jetzt nicht auf große Datenmengen limitieren, auch auf kleine Datenmengen. Eigentlich alles, wo du nicht sofort eine Response brauchst, was halt zeitunabhängig ist. Es gibt sogar Leute, die würden E-Commerce-Bestellungen durch ein Message-Queue-System jagen. Kann man auch machen, ist jetzt aber sehr wahrscheinlich nicht der prädestinierteste Anwendungsfall. Also überall da, wo die Response-Zeit delayed werden kann.
Wolfi Gassler (00:10:48 - 00:11:07)
Okay, jetzt habe ich so einen Anwendungsfall und jetzt würde ich mir das ganz klassisch selber in meiner Datenbank zusammenstricken. Ich speichere das irgendwo rein in eine Tabelle, das ist meine Warteschlange und dann speichere ich dazu, ob das bearbeitet ist oder nicht und dann baue ich mir da irgendwie so ein Ding, was da die Datenbank ständig abfragt und weiterschickt. Habe ich dann eine Message Queue?
Andy Grunwald (00:11:07 - 00:12:07)
Ja, prinzipiell schon. Also generell besteht eine Message Queue aus drei Komponenten. Auf der einen Seite hast du irgendwas, was deine Nachricht erzeugt, also sagt, hey, hier hast du was zu verarbeiten. Dann hast du was in der Mitte, eine Warteschlange, in deinem Fall zum Beispiel eine Tabelle. Da packst du diesen Job, diesen, hey, das muss verarbeitet werden, rein. Und dann hast du die dritte Komponente, irgendein Prozess, was sich diesen Job nimmt und verarbeitet. Die erste Komponente, die die Nachricht erzeugt, nennt man Producer oder Publisher. Die Tabelle, wo du das reinschreibst, nennt man eigentlich Queue beziehungsweise Warteschlange. Und das Moped, was sich diesen Job aus der Warteschlange, aus der Queue nimmt, nennt man entweder Worker oder Consumer. Wenn du all das in deiner Datenbank abbilden kannst, dann hast du eigentlich eine Basis Message Queue. Jetzt hattest du das ganze Konzept mit einer Datenbank in Verbindung gebracht. Du kannst dir das auch alles selbst bauen, indem du zum Beispiel eine relationale Tabelle einfach nur als Queue, also als Warteschlange nutzt. Machen auch sehr viele.
Andy Grunwald (00:12:10 - 00:12:29)
Ist auf jeden Fall recht simpel. Es gibt aber dedizierte Systeme für Message Queuing, also so wie es MySQL und Postgre für relationale Datenbanken gibt. Oder von mir aus auch Oracle oder MariaDB. Gibt es natürlich auch für den Message Queue Anwendungsfall dedizierte Systeme, wie zum Beispiel RabbitMQ, ActiveMQ oder oder oder.
Wolfi Gassler (00:12:30 - 00:12:35)
Und warum sollt ihr dann so dedizierte Systeme verwenden? Jetzt habe ich eh schon die Datenbank und kann das in die Datenbank speichern.
Andy Grunwald (00:12:35 - 00:13:17)
Naja, Message Queueing ist halt auch nicht ganz so einfach. Und zwar gibt es da so ein paar Fallstricke, so ein paar Tricky Parts, die diese dedizierten Systeme natürlich lösen. Auf der einen Seite geht es nämlich um die Fragestellung, wie oft kann, darf, muss beziehungsweise sollte denn eine einzelne Nachricht an einen Consumer, an einen Worker abgeliefert werden. Da geht es um die Stichwörter exactly once, at least once, at most once delivery. Wer in deiner Architektur, also die Datenbank bzw. der Consumer, wer stellt da sicher, dass jede Nachricht verarbeitet wird, jede Nachricht mindestens einmal oder genau einmal verarbeitet wird?
Wolfi Gassler (00:13:18 - 00:13:29)
Also wenn ich bei einem Newsletter zum Beispiel dann an eine Person fünf E-Mails raussende, dieselbe Newsletter E-Mail, dann werden die wahrscheinlich wenig Spaß haben. Insofern will ich da eine Verarbeitung von genau einmal haben.
Andy Grunwald (00:13:29 - 00:13:47)
Ja, das ist jetzt eine gute Frage. Du willst natürlich, dass jeder in deiner Kunden Newsletter haben möchte. Das bedeutet, du wärst dann eher im Exactly Once Delivery Modus oder At Most Once Delivery Modus, weil die Frage ist, wie kritisch ist das, wenn einer deiner tausend Leute den Newsletter nicht kriegt hat?
Wolfi Gassler (00:13:48 - 00:13:53)
Aber wo ist jetzt das Problem, wenn ich es in der Datenbank mache, aber fällt? Wurde das versendet? Ja, nein? Das setze ich.
Andy Grunwald (00:13:53 - 00:14:50)
Ja, was passiert denn, wenn dein Worker, dein Consumer sich einen Job aus der Datenbank holt, der macht dann so einen Select, dann unterbricht die Verbindung und der kann nicht sagen, hey, ich habe mir die Nachricht geholt. Und in der Zeit kommt ein zweiter Worker hoch, weil es heißt ja nicht nur, dass du eine Tabelle und einen Worker hast, sondern du kannst ja eine Tabelle und 100 Worker haben, die dann um die Jobs bei der Datenbank abfragen. Und was ist, wenn du da eine Race Condition hast? Das bedeutet, wenn einer sich eine Nachricht geholt hat, die Verbindung abbricht oder Der Server stirbt, oder, oder, oder. Dann holt sich ein anderer Worker die Nachricht. Was passiert, wenn der erste Worker sich die Nachricht holt? Die Connection zur Datenbank abbricht, der Worker aber noch weiterläuft und die Nachricht dann erfolgreich verarbeitet. Der konnte aber der Datenbank nicht sagen, hey, diese Nachricht wurde schon von einem Worker geholt. Somit wacht ein zweiter Worker auf, holt sich den Job. Dann hast du dieselbe Nachricht in zwei verschiedenen Workern, zum Beispiel deinem Newsletter, und der wird dann zweimal an dieselbe Person versendet.
Wolfi Gassler (00:14:51 - 00:14:58)
Okay und die Message Queue nimmt mir das Ganze ab, die kümmert sich darum, wenn ich diese Einstellungen setze, dann kümmert sich die Message Queue um alles.
Andy Grunwald (00:14:59 - 00:15:15)
Jede Message Queue hat andere Garantien, aber prinzipiell ja. Und mit anderen Garantien meine ich ganz genau sowas wie, wird die Nachricht genau einmal zugestellt, Minimum einmal zugestellt oder maximal einmal zugestellt. Exactly once, at least once delivery, at most once delivery.
Wolfi Gassler (00:15:15 - 00:15:21)
Jetzt hast du von 100 Workern gesprochen. Was ist jetzt so ein Worker und warum brauche ich 100 davon? Macht ja alles komplizierter.
Andy Grunwald (00:15:22 - 00:16:55)
Naja, generell redet man da von granulare Skalierbarkeit. Jetzt stell dir mal vor, wir haben Black Friday und da kommen auf einmal ganz viele Bestellungen rein oder ganz viele neue Newsletter-Abonnenten und denen willst du natürlich auch alle deinen ersten Newsletter senden. Und wenn du jetzt in der Regel pro Woche zwei neue Newsletter-Abonnenten hast und jetzt zu Black Friday hast du nämlich, bietest du den Gutschein an, über 20% und auf einmal kriegst du 10.000, Dann kannst du natürlich die Warteschlange für deinen Newsletter natürlich einzeln skalieren, weil dann kommen sehr viele Nachrichten in der Newsletter-Warteschlange und dann kannst du sagen, oh, ich brauche nicht nur einen Newsletter-Consumer, sondern auf einmal 100 und buff, werden die innerhalb von wenigen Minuten relativ schnell abgearbeitet. Also du kannst natürlich auch dann deinen Load und deine Anfragen deutlich besser parallelisieren. Du kannst die Verarbeitung auf verschiedene Server, auf verschiedene Maschinen verteilen und dadurch hast du natürlich auch eine erhöhte Ausfallsicherheit. Und wenn du dir darüber ein bisschen Gedanken machst, dann hast du natürlich eine vereinfachte Entkopplung. Also reden wir mal von Microservices. Message Shearing kann auch super dafür genutzt werden, damit zwei Microservices miteinander sprechen. Die müssen keine synchrone Kommunikation haben, wie zum Beispiel HTTP-Calls hin und her, sondern die können auch über eine dritte Komponente, wie zum Beispiel eine Warteschlange in der Mitte, asynchron miteinander kommunizieren. Und das kann dir natürlich helfen, wie zum Beispiel bei einer Migration von Monolithen auf Microservices, damit du das nicht mit einer Big Bang Migration machen kannst, sondern dass du einfach ganz normal und ganz langsam wirklich zu Microservice oder vielleicht sogar Serverless, nehmen wir mal Lambda Functions oder ähnliches, migrieren kannst.
Wolfi Gassler (00:16:56 - 00:17:21)
Okay, nehmen wir mal an, ich habe da jetzt mein Projekt und glaube, dass Message Queuing mir helfen würde, um das zu entkoppeln oder zu vereinfachen. Und du hast ja schon erwähnt, RabbitMQ ist so, würde ich sagen, das bekannteste, das mir auch so immer unterkommt, wenn es um Message Queues geht. Wenn ich mir da jetzt RabbitMQ reinhole in mein Projekt, was ist denn RabbitMQ eigentlich? Was für ein Schiff hole ich mir denn da an Bord? Kann man sich ein Schiff an Bord holen? Egal. Was ist RabbitMQ?
Andy Grunwald (00:17:22 - 00:17:28)
Also jedes Kreuzfahrtschiff hat auf jeden Fall so ein kleines Paddelboot und wenn du möchtest ist für ein kleines Paddelboot bestimmt auch ein Schiff für dich, ja.
Wolfi Gassler (00:17:29 - 00:17:33)
Jetzt hast du die ganzen RabbitMQ-Fans schon beleidigt, dass es nur ein BattleBot ist.
Andy Grunwald (00:17:33 - 00:18:24)
Also RabbitMQ ist schon ein Schiff, muss man schon sagen. Aber prinzipiell ist es halt der Marktführer. Es ist ein Open-Source-Message-Broker. Und als Message-Broker bezeichnet man eigentlich eine neue Technologie-Komponente, die sich primär um den Anwendungsfall von Message-Queuing kümmert. Das ganze Ding ist in Erlang geschrieben. Warum ist das wichtig zu erwähnen? Das Besondere an Erlang An der Sprache ist, dass sie speziell um die Fähigkeiten von Parallelität, hohe Verfügbarkeit, Fehlertoleranz und das Auswechseln von Modulen zur Laufzeit entwickeln wurde. Damals primär für die Telekommunikationsindustrie, wurde alles in Ericsson entwickelt, deswegen eher lang, heißt auch Ericsson Language für die Leute, die sowas zum ersten Mal hören. Und ich erwähne das, weil diese Sprache schon recht prädestiniert ist für ein verteiltes System, wie zum Beispiel eine Message-To-Server.
Wolfi Gassler (00:18:24 - 00:18:30)
Wie viel Kontakt habe ich da zu diesem Erlang, wenn ich jetzt diese Software verwende, muss ich Erlang verstehen irgendwie?
Andy Grunwald (00:18:30 - 00:18:47)
Für die Anwendung vom System eher nicht, für den Betrieb musst du auch kein Erlang lesen können. Wenn du ein RabbitMQ Cluster aufsetzen möchtest, kommst du dann mal kurz in Berührung mit so Sachen wie einem Erlang-Cookie und Co. und Erlang-Virtuellen Maschinen und so weiter und so fort.
Wolfi Gassler (00:18:47 - 00:18:51)
Okay, aber für den normalen Anwendungsfall kann ich ja einfach losstarten.
Andy Grunwald (00:18:51 - 00:19:17)
Der normale Anwendungsfall, da wirst du eigentlich mit Erlang nicht in Kontakt kommen, weil die ganze Sache eigentlich um das AMQP-Protokoll gebaut ist, das sogenannte Advanced Messaging Queuing Protocol. Ist ein offener Standard seit 2011. Und weil es ein toller offener Standard ist, gibt's natürlich diverse Client-Libraries in Java, .NET, Ruby, Python, PHP, JavaScript, Go, Objective-C, Swift, Rust. Und mich würd auch nicht wundern, wenn eins in Lowell-Code gibt.
Wolfi Gassler (00:19:17 - 00:19:27)
Das heißt eigentlich, wenn ihr das verwendet, dann in meiner Sprache ist das komplett abstrahiert und ihr verwendet dann nur diese Library oder den Client, der sich dann um alles kümmert.
Andy Grunwald (00:19:27 - 00:20:09)
Genau. Und diese Client Library, die spricht dann AMQP. AMQP selbst ist ein binäres Netzwerkprotokoll, was damals in der Bankenwelt erfunden wurde. Und zwar ist es recht interessant, wo die ganze Sache herkommt. 2003 haben Mitarbeiter bei JP Morgan die ganze Sache entwickelt, haben gesagt, hey, damals war, JMS so ein Riesending. JMS, falls du dich erinnerst, war Jakarta Messaging, ganz früher Java Messaging Service. Also du merkst schon, wir sind schon wieder ganz in der Java-Welt. Und da sind wir natürlich in der kompletten Banken- und Finanzindustrie. Und die ganze Banken- und Finanzindustrie, die war nämlich relativ groß im Bereich MOM. Und MOM steht für Message-orientierte Middleware.
Wolfi Gassler (00:20:10 - 00:20:15)
Also langsam haben wir ein Bingo, aber in dieser Java-Welt ist es immer das Gleiche, diesen Abkürzungen.
Andy Grunwald (00:20:15 - 00:21:15)
So, und die Jungs und Mädels dachten sich, Hämmer, pass mal auf, wär doch ziemlich cool, wenn wir mal einen Standard haben, und der vielleicht sprachunabhängig ist. Und so haben die angefangen, AMQP zu entwickeln. Und so, wie es halt natürlich immer ist, wenn so eine große Bank wie JP Morgan Chase mit so was um die Ecke kommt, dann sagen die anderen Banken, so wie die Bank of America, die Barclays Bank, Goldman Sachs, bla bla bla, Jungs, was macht ihr da? Ihr revolutioniert gerade irgendwie unsere Message-Mittelwehr. Da will ich mitmischen. So und so hat sich dann ein Konsortium aus Finanzinstitutionen entwickelt. Natürlich war da auch Reddit und 4MWare und Microsoft und Cisco dabei. Und die haben dann angefangen an dem offenen Standard da rumzuschrauben. Der Erfolg von AMQP kam eigentlich daher, dass AMQP eigentlich alle Features von dem vorherigen JMS, also von dem Jakarta Messaging, mit implementiert. Das bedeutet, die ganzen Finanzindustrien konnten also eigentlich direkt auf den neuen Standard wechseln.
Wolfi Gassler (00:21:15 - 00:21:25)
Heißt das, ich brauche gar keinen Revit MQ Client, sondern kann einen allgemeinen AMQP Client verwenden und da kann dann kommunizieren mit Revit MQ?
Andy Grunwald (00:21:25 - 00:21:52)
Genau, du bist ja jetzt nicht an Revit MQ gebunden. Du kannst auch sowas anders machen wie Active MQ oder einen JBoss AMQ oder SWIFT MQ oder von mir aus auch bei Microsoft Azure gibt es den Azure Service Bus. All die supporten auch das AMQP Protokoll, was seit 2011 in Version 1 standardisiert ist. Und von mir aus kannst du jetzt auch deinen eigenen Message Queue Server schreiben, der AMQP spielt.
Wolfi Gassler (00:21:53 - 00:22:12)
Das klingt für mich jetzt eigentlich alles sehr schrecklich. Für mich als Open-Source-Mensch, der irgendwie leichtgewichtige Sachen haben will und du bekommst da jetzt mit irgendwelchen Java- und Bankengeschichten und schlag mich tot, ist das was für mein Open-Source-Projekt oder verheirate ich mich dann mit irgendwelchen Java-Enterprise-Zeug?
Andy Grunwald (00:22:12 - 00:22:59)
Mit Java hast du nix am Hut und ich bin bei weitem kein JVM-Freund, aber mit Java hast du nix am Hut und ja, RabbitMQ ist halt schon nicht ganz leichtgewichtig, aber es ist immer die Frage, was brauchst du? Willst du eigentlich nur eine Warteschlange haben, dann ist dein Datenbank-Anwendungsfall, den du am Anfang erwähnt hast, vielleicht auch gar nicht so verkehrt. Möchtest du das gar nicht in der Datenbank implementieren, weil du vielleicht gar keine relationale Datenbank hast, kannst du natürlich auch ohne Probleme dir etwas leichteres ins Haus holen, wie zum Beispiel Amazon SQS, was für Simple Queuing Service steht. Das bietet dir nicht die Features an, die dir ein dedizierter Message Broker zur Verfügung stellt, sondern nur eine simple Warteschlange. Aber da muss ich dir leider mit dieser Consulting-Antwort kommen, it depends.
Andy Grunwald (00:23:02 - 00:24:02)
In der Einleitung hatten wir simpel erwähnt, dass eine Message Queue aus drei Komponenten besteht. Jemanden, der die Nachricht erzeugt, einen Producer. Jemanden in der Mitte, die sogenannte Warteschlange, die Queue. Und jemand am Ende, der die Nachricht aus der Queue nimmt und verarbeitet, der Consumer. Jetzt ist es doch nun mal so, dass das eine sehr, sehr vereinfachte Ansicht auf die Problemstellung ist. Denn wenn du über die Zustellung von Nachrichten sprichst, dann kommen dir auch relativ schnell komplexe Szenarien in den Sinn. Nehmen wir zum Beispiel mal den Anwendungsfall, du hast eine Nachricht, die möchtest du in mehrere Queues packen. Der Wolfgang lädt auf Twitter ein neues Avatar hoch und die Information, dass dieses Avatar, dieses Bild jetzt verarbeitet werden muss, soll in vier verschiedenen Queues. Eine Queue, die konvertiert das nach PNG, eine nach JPEG und die dritte nach SVG und die vierte geht ans AI-Modell, was dann mit Hilfe deines Bildes wieder das Modell trainiert. Wie würdest du sowas zum Beispiel mit einer Datenbanklösung machen? Du würdest mit hoher Wahrscheinlichkeit eine Nachricht mit vier Inserts in vier verschiedene Tabellen schreiben, oder?
Andy Grunwald (00:24:04 - 00:24:57)
Bei einem dedizierten Message Broker hast du halt so Konstrukte drumherum wie Exchanges und Routes. Das bedeutet, du hast auf der einen Seite vier Warteschlangen, aber vor den vier Warteschlangen hast du so eine Art Loadbalancer geschaltet. Deine Applikation schickt nur die Nachricht, Wolfgang hat ein neues Bild hochgeladen an den Loadbalancer, an den sogenannten Exchange, und der Exchange kümmert sich dann um die Verteilung deiner Nachricht in vier verschiedene Queues, abhängig von der Konfiguration von dem Exchange. Und dann kannst du sagen, hey lieber Loadbalancer, also hey lieber Exchange, da gibt es noch einen Routing Key. Dein Routing Key kann zum Beispiel das Format, in dem du das Bild hochgeladen hast, PNG, JPEG und Co. Weil wenn du PNG hochgeladen hast, muss die Nachricht ja nicht in die PNG Queue rein, weil ein PNG nach PNG konvertieren wäre ein bisschen doof. Du kannst dann anhand von Regeln sagen, okay, in welche Queues diese Message dann inserted werden soll.
Andy Grunwald (00:25:01 - 00:25:36)
Und dann kannst du halt die Nachrichten in die verschiedenen Queues routen. Du kannst halt sagen, okay, route die bitte von einem Exchange in eine Queue. Oder du kannst ein Fanout machen. Jede Nachricht, die an diesen Exchange kommt, geht in alle Queues. Oder du kannst anhand von Regeln der Nachricht in spezifische Queues routen, zum Beispiel in drei von fünf oder ähnliches. Wenn wir von solchen Features reden, reden wir aber auch von Sachen wie Priority Queues oder Priority Messages. Mit hoher Wahrscheinlichkeit, wenn du mehr und mehr Message Queuing in deinem System verwendest, wirst du auch Nachrichten haben, die einen höheren Stellenwert haben als andere.
Wolfi Gassler (00:25:36 - 00:25:43)
Meine haben primär immer höchste Priorität. Kann man das implementieren? Wenn der User Wolfgang dran ist, werden immer priorisiert.
Andy Grunwald (00:25:44 - 00:26:30)
Genau das kann man tun. Nehmen wir mal ein Beispiel. Die Verarbeitung deiner Finanzdaten sind mit hoher Wahrscheinlichkeit deutlich wichtiger als die Konvertierung deines Avatars. Oder die Newsletter sind mit hoher Wahrscheinlichkeit wichtiger als die Verarbeitung deiner Log-Dateien. Mithilfe von Priority-Warteschlangen oder Priority-Nachrichten kannst du halt den Consumern, also den Workern, die deine Nachricht verarbeiten, wirklich sagen, okay, behandle die mal bitte mit der Priorität. Du kannst aber auch sagen, hey, alle Nachrichten, die ich in eine spezifische Warteschlange packe, haben nur eine gewisse Gültigkeit, sogenannte Time-to-Live-Nachrichten. Und wenn die in der Zeit nicht verarbeitet werden, entfallen die. Der Grund für die, warum die nicht verarbeitet werden, kann vielfältig sein. Entweder weil da gerade keiner auf dieser Queue lauscht oder weil da zu viel drauf ist oder oder oder.
Wolfi Gassler (00:26:30 - 00:26:51)
Wie mache ich das dann mit Logging und Monitoring? Ich muss das ja irgendwie meistens zumindestens mitbekommen, wenn da irgendwas schief geht. Und habe ich da dann auch Schnittstellen, um irgendwelche Monitoring-Tools und ähnliche Sachen anzubinden? um zu sehen zum Beispiel, wie viele Messages jetzt aufgrund dem TTL nicht verarbeitet worden sind oder oder verworfen worden sind.
Andy Grunwald (00:26:51 - 00:27:46)
All die Informationen gibt ihr RabbitMQ raus, entweder in einem schönen Dashboard oder von mir aus auch als Prometheus-Exporter, damit du die im Grafana haben kannst oder oder oder. Sowas ist alles mitgeliefert. Eins der Killer-Features, die eigentlich bei jedem dedizierten Message-Broker verfügbar ist, ist das sogenannte Message-Acknowledgement und die Rejections. Das bedeutet, du hast einen Consumer, der connectet sich zu einer Queue und sagt, lieber Message Broker, falls eine neue Nachricht reinkommt, gib mir die mal. Der Message Broker liefert diese Nachricht dann an den Consumer und reserviert diese Nachricht auf den Message Broker und hält sie vor, dass kein zweiter Consumer diese selbe Nachricht zugestellt bekommt. Mein Consumer, der die Nachricht jetzt hat, kann die verarbeiten und kann am Ende der Verarbeitung sagen, acknowledged. Und durch dieses Acknowledged teilt der Consumer dem Message Broker mit, diese Nachricht wurde erfolgreich verarbeitet.
Wolfi Gassler (00:27:46 - 00:28:18)
Das müsste man in meiner Datenbanklösung natürlich alles selber programmieren, müsste damit Datenbanktransaktionen herum hantieren und vielleicht irgendwie zwischendrin in die Tabelle speichern. Das ist aktuell in Bearbeitung. Dann was passiert, wenn die Transaktion ausläuft, wenn der Broker weg stirbt? Also diese ganzen Sachen müsst ihr dann implementieren und vor allem verstehen und bei einem Message Broker hat sich da jemand beziehungsweise meistens eine Gruppe schon jahrelang Gedanken darüber gemacht, wie man die ganzen Edge Cases abfängt und behandelt.
Andy Grunwald (00:28:19 - 00:28:50)
Richtig, und das ist nämlich der Killer-Unterschied. Und wenn wir jetzt von diesem Message Acknowledgement sprechen, da reden wir von einem Happy Pass. Aber was passiert, wenn da mal was schief geht? Der Gegensatz zum Message Acknowledgement sind Message Rejections. Das bedeutet, stell dir vor, du kriegst eine Nachricht als Consumer, verarbeitest die, und die Verarbeitung ist aber nicht erfolgreich. Da kannst du das Gegenteil von Acknowledgement machen, du kannst sie rejecten, Und wenn du die rejectest, dann geht die Nachricht zurück an den Message-Broker und der Message-Broker verteilt diese Nachricht an einen anderen Consumer weiter.
Wolfi Gassler (00:28:50 - 00:28:58)
Kann man da auch dann irgendwie Regeln drüber legen? Zum Beispiel, wenn jetzt ein E-Mail-Versand fehlschlägt, dass der einfach erst in 10 Minuten wieder probiert wird oder sowas?
Andy Grunwald (00:28:58 - 00:29:58)
Ob RabbitMQ selbst jetzt gerade so Delayed Messages kann, weiß ich jetzt gerade nicht. Müsste man nachgucken. Sowas kann man aber natürlich relativ einfach bauen. Und jetzt haben wir gerade von diesem Acknowledgement und dem Reactions gesprochen. Das machst du ja aktiv. Aber was passiert, wenn der Consumer einfach gar keine Rückmeldung kriegt? Der kriegt eine Nachricht und Timed Out, stirbt oder ähnliches. Dann kannst du eine Dead Letter Queue einrichten. Eine Dead Letter Queue ist eine zweite Warteschlange, die nur dafür da ist, die nicht verarbeiteten Nachrichten bzw. die Nachrichten im Fehlerfall abzufangen. Und das ist natürlich für Entwickler ein Traum, weil dann kannst du nämlich in diese Warteschlange reingucken und sagen, okay, was ist an dieser Nachricht jetzt so speziell, dass diese nicht erfolgreich verarbeitet werden konnte? Und so kannst du dein System kontinuierlich verbessern, Fehlerfälle rausbügeln usw. Und du kannst diese Nachrichten aus dem Dead Letter Queue natürlich wieder in die Original Queue einspielen und somit wirklich sicherstellen, dass all deine Nachrichten verarbeitet werden.
Wolfi Gassler (00:29:59 - 00:30:17)
Aber ich muss natürlich da auch reinschauen, wenn ich das einfach nur blind laufen lasse, dann habe ich natürlich irgendwann ein Problem, wenn die Messages nicht verarbeitet werden, wenn ich das nicht sauber monitor das ganze. Also ich habe schon wieder das Problem, dass ich eine zusätzliche Komponente habe, die ich auch verstehen muss, monitoren muss, dementsprechend reagieren muss.
Andy Grunwald (00:30:17 - 00:30:29)
Ja alles richtig, aber du kaufst ja auch keinen Neuwagen und fährst dann einfach 200.000 Kilometer ohne Ölwechsel. Also die neue Komponente ist halt genauso wie jedes andere Teil in deinem Software-Stack. Und wenn du nicht drum kümmerst, dann rostet das natürlich ebenfalls.
Wolfi Gassler (00:30:30 - 00:30:54)
Aber ich muss mir halt im Klaren sein, dass ich mir da wieder was zusätzlich reinhole und was man vor allem auch verstehen muss. Und gerade in dem Bereich ist es ja auch gar nicht so leicht, immer alles zu verstehen, gerade so Asynchronität, Fehlerfälle, diese ganzen Garantien oder eben nicht Garantien, ob etwas ausgeliefert wird, nur einmal ausgeliefert wird. Also es ist schon auch ein komplexes Thema, mit dem man sich beschäftigen muss. Das ist nicht einmal install und dann läuft alles, sondern man sollte sich schon ein bisschen damit beschäftigen.
Andy Grunwald (00:30:54 - 00:31:11)
Und das, meine ich ja genau, ist der große Unterschied zu deiner Datenbanklösung. Deine Datenbanklösung ist nichts Falsches. Doch die Frage ist, möchtest du dir all diese Gedanken, die sich eine Gruppe von sehr intelligenten Menschen gemacht hat, für diese Anwendungsfälle selbst machen und neu programmieren, oder möchtest du einfach was Vorgefertigtes nehmen?
Wolfi Gassler (00:31:11 - 00:31:24)
Wenn ich jetzt sowas verwende, wie du erwähnt hast mit der Cloud zum Beispiel von Amazon, dieses SQS, muss ich mir dann weniger Gedanken machen? Ist dieses Simple dann so simple, dass ich es einfach verwenden kann?
Andy Grunwald (00:31:24 - 00:32:16)
Ja, ist es, aber du kannst jetzt dann auch nur simple Anwendungsfälle abbilden, beziehungsweise brauchst mehr Glue-Code drumherum. Nehmen wir mal ein Beispiel. Bei SQS gibt es jetzt keinen simplen Weg, eine Nachricht an mehrere Consumer zu stellen, weil was du hast, ist du hast eine Queue, da packst du eine Nachricht rein und diese Queue wird von einem Worker verarbeitet. Du hast jetzt nicht sowas wie den Exchange, den sogenannten Load Balancer, von dem ich gerade gesprochen habe. Das müsstest du dann selbst bauen, wie du hast eine Lambda Function an deiner SQS und immer wenn eine Nachricht in die erste Queue reinkommt, nimmt die Lambda Function die Nachricht und packt die in drei andere Queues auf Basis von deinen Regeln. Und diese Regeln musst du alle selbst in der Lambda Function dann programmieren, wo du die beim Exchange, bei RabbitMQ zum Beispiel, ganz einfach hinterlegen kannst.
Wolfi Gassler (00:32:16 - 00:32:21)
Aber das Monitoring muss ich trotzdem noch machen. Dead Letter Queue oder sowas.
Andy Grunwald (00:32:21 - 00:32:56)
Eine Dead Letter Queue gibt es zum Beispiel bei SQS dann gar nicht. Das müsstest du dann auch alles selbst bauen. Da würdest du dann die klassische Amazon Cloud-Lösung für Monitoring, CloudWatch und Co. nehmen. Bei Amazon selbst gibt es aber neben SQS auch noch Amazon MQ, was ein vollständig verwalteter Open-Source-Message-Broker ist. Da weiß ich gar nicht, ob da jetzt hinter einem Rabbit MQ steht oder nicht. Aber mich würde sehr stark wundern, wenn der sehr weit weg von den RabbitMQ Anwendungsfällen ist. Nur das ist dann natürlich bei weitem nicht mehr so simpel wie SQS, der Simple Queuing Service von Amazon.
Wolfi Gassler (00:32:56 - 00:33:07)
Damit wir jetzt nicht nur Werbung für Amazon machen, Google hat natürlich das gleiche PubSub und wahrscheinlich gibt es noch ganz viele andere Angebote, die gehostet sind. Zu Google PubSub, was ist da der Unterschied?
Andy Grunwald (00:33:07 - 00:34:04)
Ja, Google hat jetzt nicht genau das gleiche. Und zwar ist das jetzt ein Publish-Subscribe, weil Publish-Subscribe, also Pub-Sub, ist ein bisschen was anderes als Message-Queuing. Bei Publish-Subscribe sagt man üblicherweise ist, man publischt was und wenn, zum Beispiel in eine Warteschlange, aber wenn da keiner an der Warteschlange horcht, dann ist das, ich schrei in den Wald hinein und die Message geht verloren. Wohin du gegen bei Message Queuing in der Regel eine Warteschlange dazwischen hast, die dann, auch wenn es gerade keine Consumer gibt, deine Nachricht zwischenspeichert. Wohingegen bei PubSub in der Regel kein persistenter Storage mittendrin. Das ist so der klassische Unterschied zwischen Message Queuing und PubSub. Wenn kein Subscriber da ist, dann geht die Published Message auch einfach verloren. Was im Cloud-Umfeld in der Regel nicht passiert, weil du bei Google zum Beispiel in der Regel eine Cloud-Funktion danach hast, die eigentlich immer an deiner Pub-Sub-Queue hängt.
Wolfi Gassler (00:34:04 - 00:34:21)
Ja, vor allem geht es ja darum, dass die subscribed ist. Das heißt nicht, dass die sofort reagieren muss, weil es ist ja genauso ein Worker, der eine Minute später das konsumieren kann, aber er muss halt registriert sein, dass er hocht auf diese Messages, weil intern wird das ja genauso zwischengespeichert irgendwo bei Google. Aber vom Konzept her ist es natürlich was anderes.
Wolfi Gassler (00:34:22 - 00:34:31)
Wenn ich mir jetzt nicht dieses große Schiff an Bord holen will, aber auch keine Cloud-Lösung verwenden will, gibt es irgendwelche anderen simpleren Lösungen abseits von meiner Datenbank?
Andy Grunwald (00:34:31 - 00:34:39)
Was sehr viele Leute nutzen als Alternative ist zum Beispiel Redis. Und Redis würde man jetzt eigentlich nicht in Verbindung mit Message Queuing bringen, Aber.
Wolfi Gassler (00:34:40 - 00:34:45)
Du machst das, weil du einfach so ein großer Redis-Fan bist. Das wissen wir jetzt alle mittlerweile.
Andy Grunwald (00:34:45 - 00:35:35)
Redis hat einfach zwei oder fast sogar drei Komponenten, die für diesen Anwendungsfall ganz gut zu gebrauchen sind. Auf der einen Seite hat Redis auch eine ganz klassische PubSub-Methode, ähnlich wie Google PubSub. Schmeißt du da eine Nachricht rein. Und wenn Subscriber da sind, kriegen die die. Das ist ein 1 zu N Modell. Die zweite prädestinierte Datenstruktur sind eigentlich ganz klassische Listen. Weil eigentlich, wenn du ganz weit weg gehst und die Details mal ausblendest, ist eine Message Queue auch eigentlich eine Liste. Du packst oben einen neuen Eintrag rein, deine neue Nachricht und nimmst die unten wieder raus. Und das kannst du natürlich mit Redis auch machen. Man muss natürlich ein bisschen aufpassen, wie groß deine Queue, also deine Liste wird, aber mit klassischen Listenbefehlen wie Push und Pop kannst du dir natürlich da auch eine Art persistente Wartestange aufbauen.
Wolfi Gassler (00:35:35 - 00:35:44)
Musst aber natürlich im Hintergrund auch wieder viel im Kopf mitdenken und dementsprechend beachten. Also du bekommst jetzt kein vollwertiges Message Queuing System da.
Andy Grunwald (00:35:45 - 00:36:18)
Ja, all die Anwendungsfälle mit Exchange und Routing und was weiß der Gei nicht noch alles, Dead Letter Queues, Time to Live, obwohl Time to Live hat man bei Redis auch, aber all diese spezifischen Sachen wie Message Acknowledgement, Rejections und so weiter, all sowas sind natürlich da nicht, nicht da, weil Redis Listen sind halt nicht auf Message Queue ausgelegt. Und die dritte Komponente ist, die es noch gar nicht so lange bei Redis gibt, da geht es um Redis Streams. Was nicht Message Queueing ist, viele Leute missbrauchen Streams aber als Message Queueing.
Wolfi Gassler (00:36:18 - 00:36:28)
Es ist ein interessanter Punkt, wo siehst du den Unterschied zu Streams? Wo ist der Unterschied zwischen einem Message Queue und einem Streaming-System oder Streams ganz allgemein?
Andy Grunwald (00:36:28 - 00:38:00)
Nur mal ganz zur Erklärung, der Begriff Streams kam eigentlich, also den gibt es schon Ewigkeiten, In den letzten paar Jahren hat er sehr viel Popularität erhascht durch Kafka, durch Apache Kafka. Und Apache Kafka hatte die Eigenheit, wie Streams implementiert wurden. Und zwar, dass es ein Append-Only-Log war. Also das bedeutet, man hat einfach immer nur Daten dran gepackt und dann auf Disks persistiert. Ganz High-Level gesprochen. Alle Kaffee-Experten würden mich glaube ich jetzt gerade in der Luft zerreißen. Als das so populär wurde, haben andere Systeme wie zum Beispiel RabbitMQ oder wie zum Beispiel Redis auch dieses AppendOnly-Log implementiert. Wo ist jetzt genau der Unterschied zwischen Message Queueing und Streams? Auf der einen Seite ermöglichen Streams ein sogenanntes Replay oder Time Traveling. Die Nachrichten innerhalb eines Streams werden in der Regel persistiert und wenn dort ein Consumer diese Nachrichten konsumiert, werden diese Nachrichten nicht aus der Queue gelöscht. Weil es ist keine Queue, es ist eigentlich nur ein Append-Only-Log. Und der Consumer konsumiert die Nachrichten und speichert sich intern. Oh, ich habe die fünfte Nachricht schon gelesen, deswegen muss ich bei der sechsten wieder anfangen. Wohingegen das Message-Queue-System die Message an den Consumer zustellt und dann diese zugestellte Nachricht nicht für einen zweiten Consumer verfügbar ist. Das ermöglicht natürlich auch, dass du in einem Stream alle Daten replayen kannst, beziehungsweise Time-Traveling machen kannst. und zwar einfach zu der zehnten, zwanzigsten oder vierzigsten Nachricht springen kannst.
Wolfi Gassler (00:38:01 - 00:38:36)
Also wenn man zum Beispiel jetzt ein Use Case annimmt, man verarbeitet die Logs von ganz vielen Servern und speichert die in einem Elasticsearch Cluster ab und mir schmiert dieser ganze Elasticsearch Cluster ab, wenn ich das über ein Message Queuing System gelöst habe, dass die Logdaten weitergeleitet werden. Dann habe ich ein Problem, den wieder aufzubauen von Null, wenn der mir abschmiert und alle Daten weg sind. Aber wenn ich einen Stream habe, kann der einfach wieder bei Null beginnen, kann sich wieder alles einlesen, wird zwar eine lange Zeit brauchen, aber dann habe ich alle Daten wieder in meinem Elasticsearch Cluster drinnen. Das heißt, es ist fast so wie ein Backup, wenn man das so sehen will.
Andy Grunwald (00:38:37 - 00:38:50)
Wenn man das so sehen möchte, es gibt in der Streaming-Community ja die große Diskussion, ist Kafka eine Datenbank? Und da gibt es bestimmt Gründe dafür und Gründe dagegen. Die Frage werden wir hier nicht beantworten, aber so kann man das sehen.
Wolfi Gassler (00:38:50 - 00:39:01)
Aber jetzt hast du schon Kafka erwähnt. Kann ich Kafka jetzt auch verwenden als ein Message-Queuing-System in dem Sinne, wenn ich das zum Beispiel jetzt schon irgendwo in Verwendung habe?
Andy Grunwald (00:39:02 - 00:40:15)
Kannst du, es ist nicht der prädestinierte Anwendungsfall dafür, weil auch diese spezifischen Eigenheiten von einem Message Queue System sind da nicht verfügbar. Der große Unterschied ist, dass du gegebenenfalls mehr Logik im Client, also im Consumer haben musst. Weil der Consumer muss sich mitspeichern, welche Nachricht du bereits konsumiert hast. So Sachen wie Rejection und Acknowledgement gibt's da nicht, wird aber auch eigentlich nicht benötigt, da eine Nachricht ja auch von mehreren Consumern verarbeitet werden kann, was ein großer Unterschied ist. Besonders wenn du einen Use Case hast von sogenannten Large Fanouts, du hast also eine Warteschlange, und ganz viele Consumer müssen eine Nachricht verarbeiten, Dann ist sowas wie Streaming natürlich schon besser. Nehmen wir mal als Beispiel Mobile Push Notifications. Du hast eine Warteschlange, ein Stream, da gehen Push Notifications rein und du hast ganz viele Handys, die darauf lauschen und müssen dann den Ping kriegen, dass jetzt irgendein Angebot verfügbar ist. Dann ist sowas wie Streaming natürlich bevorzugt gegenüber Message Queuing, weil bei Message Queuing müsstest du ganz viele Queues haben, also du müsstest ein Queue pro Handy haben, wenn du so möchtest. Weil wenn die Nachricht verarbeitet ist, dann ist sie ja aus der Queue raus. Also das ist so ein großer Unterschied.
Wolfi Gassler (00:40:15 - 00:40:21)
Wobei mit PubSub würde das ganz gut funktionieren, oder? Das ist genau für diesen Use Case auch gemacht worden, dass ich viele Subscriber habe.
Andy Grunwald (00:40:21 - 00:40:29)
Mit PubSub wird das auch funktionieren, mit dem großen Unterschied, dass die Nachricht dann nicht persistent wäre, weil die ist ja dann auch lost.
Wolfi Gassler (00:40:29 - 00:40:51)
Nachdem du ja auch bei einer Firma arbeitest, die Kafka hostet, anbietet, Was würdest denn du sagen, wenn du jetzt ein Message Queuing System brauchst, also wirklich nur ein klassisches Message Queuing System? Ist RabbitMQ einfacher aufzusetzen oder Kafka? Weil Kafka ist ja der neue heiße Scheiß und ich will mich eigentlich wirklich mit den neuen Technologien immer beschäftigen, RabbitMQ ist ja schon zu alt.
Andy Grunwald (00:40:51 - 00:42:56)
Das ist eine Scheißfrage. Also das ist wirklich auf deinem Anwendungsfall und welchen Scale du hast. Also wenn wir sagen RabbitMQ ist ein Schiff, dann ist Kafka gegebenenfalls eine Raumstation. Also Kafka und RabbitMQ zu vergleichen ist sehr sehr schwierig, weil die Natur von beiden Systemen ist sehr unterschiedlich. Kafka ist von Haus aus ein verteiltes System, was RabbitMQ von Haus aus nicht ist. RabbitMQ supportet auch Cluster. Ja, alles schön gut, aber... In der Regel betreibt man keinen One-Node-Kafka-Cluster. Ein Kafka-Cluster ist das Minimum, was du eigentlich betreibst mit drei Nodes. Wohingegen beim RabbitMQ du auch ohne Probleme mit einem Active-Passive, also mit einem Zwei-Node-Cluster, super zurande kommen kannst. Es kommt halt wirklich ganz auf deinen Use-Case drauf an, weil da bin ich eher der Fan, nutze das richtige Tool für das richtige Problem. Willst du Streaming oder Message-Queuing machen? Bei Kafka kommt halt eine enorme Komplexität mit, was natürlich auch den Aufbau von einem Cluster supportet, wie zum Beispiel Zookeeper. Klar, da gibt's in der Kafka-Community gerade so Diskussionen oder neue Features wie K-Raft, dass du Zookeeper-less-Kafka-Cluster betreiben kannst und so weiter und so fort. Das ist aber noch gar nicht so weit fortgeschritten. Und da gibt's auch noch so andere geile Features, so wie Tiered Storage, dass du deinen Kafka ... deine Kafka-Daten auf Object-Storage ablegen kannst und so weiter und so fort. Aber du merkst schon, das geht halt schon so super in so recht große Enterprise-Use-Cases, wohingegen ein klassischer RabbitMQ jetzt auch nicht ganz so einfach zu betreiben ist. Aber für Kafka ist halt schon wirklich bevorzugt, dass du da Leute hast, die sich dediziert drum kümmern. Aber es kommt da wirklich drauf an, was du machen möchtest, ja? Also, wenn du wirklich klassisches Message-Queueing hast, dann würde ich dir auch ein Message-Queue-System empfehlen. Hast du Kafka in deinem Stack schon drin, und brauchst alle die dedizierten Message-View-Funktionalitäten nicht, dann könnte man auch überlegen, ob es den Aufwand wert ist, eine neue Komponente in den Stack zu introducen. Ich würde jetzt aber auch nicht ein Message-View-System als Streaming nutzen, weil das sind halt auch andere Anwendungsfälle, weil ein RabbitMQ kriegt in der Regel nicht den High-Performance-Durchsatz wie ein Kafka auf Basis der Detailimplementierung.
Wolfi Gassler (00:42:56 - 00:43:10)
Okay, dann gehen wir mal zurück zu Message Queues, weg von Streaming, bleiben wir bei diesem Thema. Wie sieht es denn mit ZeroMQ aus? Weil ich habe immer ganz oft gehört, ZeroMQ ist wie RabbitMQ, nur viel leichtgewichtiger und besser und cooler.
Andy Grunwald (00:43:11 - 00:43:36)
Naja, ZeroMQ ist ja erstmal nur eine Library. Ist ja keine richtige Systemkomponente, also ist ja keine Applikation. ZeroMQ ist eine Library für asynchronen Nachrichtenaustausch. Und ich habe mit ZeroMQ jetzt noch nicht so viel gearbeitet, aber mein Verständnis ist, dass du ZeroMQ unter anderem in deiner Applikation embeddest, wohingegen du RabbitMQ als externe Komponente in deinem Stack betreibst.
Wolfi Gassler (00:43:36 - 00:43:53)
Also wenn ich noch einen kleineren Anwendungsfall habe, wo ich jetzt nicht hunderttausende Server habe und irgendwie über Server hinweg und verschiedene Anwendungen das Ganze realisieren muss, dann kann ich mir ZeroMQ holen und das im kleinen Stile in meiner Applikation abbilden, aber habe trotzdem diese Queuing Functionality.
Andy Grunwald (00:43:54 - 00:44:53)
Richtig, natürlich ohne die ganzen Reliability-Garantien, Ausfall und Co. Da musst du dich natürlich selbst drum kümmern, weil das natürlich dann als Embedded Library Part deiner Applikation ist. Aber ja, ich sehe das immer so ein bisschen, und der Vergleich hinkt vielleicht ein bisschen, aber wenn du ein paar Schritte zurückgehst, sehe ich ZeroMQ im Bereich Message Queueing sowie SQLite im Bereich Datenbank. weil du SQLite auch sehr oft in deiner Applikation wirklich embedden kannst, um einen SQL-ähnlichen Storage zu haben. Oder da tue ich jetzt SQLite nichts Gutes, wenn ich sage SQL-ähnlich, weil es ist natürlich schon eine vollwertige Datenbank mit allem Drum und Dran, aber sehr gut, um innerhalb deiner Applikation zu embedden. Und so ist es halt auch ZeroMQ. Ist natürlich unglaublich leichtgewichtig, ne? Also wer auf den Memory-Verbrauch achten muss, wer gar nicht so super viel spezifische MQ-Funktionalitäten braucht, Zero MQ ist auch ein Top-Ding.
Wolfi Gassler (00:44:53 - 00:44:58)
Wo würdest du denn Rapid MQ nicht einsetzen? Oder spricht irgendwas gegen Rapid MQ?
Andy Grunwald (00:44:59 - 00:46:25)
Man sollte sich halt schon überlegen, ob man RebellionPube betreiben möchte, weil es kann schon ein bisschen tricky werden, wenn man das maintainen möchte. Speziell wenn man einen Cluster betreiben möchte, dann muss man sich halt schon ein bisschen mit dem Unterbau beschäftigen. Also ich rede da von dem von Erlang, von der Erlang VM zum Beispiel. Wenn zwei Erlang-Applikationen über einen Cluster, über einen Server hinweg kommunizieren sollen, dann muss das Erlang-Cookie da sein, richtig gesetzt sein. Also ein bisschen Erlang-Knowledge im Operations-Team würde da schon Sinn machen. Oder Erlang hat auch so eine Embedded-Database, NESIA nennt sich das. Da muss man sich halt schon ein bisschen mit auseinandersetzen. Also wenn du es im Hochverfügbarkeit-Bereich einsetzen möchtest, dann überlegst du dir zweimal, ob du ein RabbitMQ einsetzen möchtest, wenn du zum Beispiel schon Kafka im Stack hast. Also da kommt es wirklich drauf an, hast du ein MQ-Use-Case, also ein Message-Q-Use-Case oder nicht. Die zweite Geschichte ist halt natürlich, welche Garantien brauchst du im Message-Q-Bereich? Also da reden wir schon von diesen harten Problemen wie Exactly-Once-Delivery. Aufgrund der Kombination von komplexem Routing und der pushbasierten Zustellung von RabbitMQ, also so wie RabbitMQ intern die Nachrichten an die Consumer zustellt, supportet RabbitMQ selbst keine Exactly-Once-Delivery, sondern eher At-Least-Once-Delivery.
Wolfi Gassler (00:46:25 - 00:46:35)
Das heißt meine Newsletter-Abonnentinnen bekommen dann wenigstens garantiert eine E-Mail zugestellt, aber können halt vielleicht auch fünfmal die gleiche bekommen, bei At-Least-Once.
Andy Grunwald (00:46:35 - 00:46:55)
Ja und nein. Also, RabbitMQ stellt die Nachricht aus der Warteschlange minimum einmal zu deinem Consumer, aber auch gegebenenfalls mehrmals. Und da ist es jetzt ganz wichtig, dass die Consumer idempotent geschrieben werden. Das bedeutet, dass sie eine Nachricht mehrfach verarbeiten können, aber immer dasselbe Ergebnis rauskommt.
Andy Grunwald (00:46:57 - 00:47:28)
Da brauchst du halt irgendwo ein zentrales Log. Hat dieser Kunde diese E-Mail schon erhalten? Und dann würdest du bei einem zweiten Processing sagen, oh, der hat die schon erhalten, deswegen acknowledge ich die einfach mal, weil RabbitMQ die Nachricht zweimal zugestellt hat. Das ist so ein klassisches Pattern bei Message Queueing generell. Und das musst du aber auch dann bei Kafka, bei Streaming beachten. Also das ist jetzt nicht RabbitMQ spezifisch, das ist generell spezifisch zu der asynchronen Verarbeitung von Nachrichten, sei es im Message-Queering-Bereich oder im Streaming-Bereich.
Wolfi Gassler (00:47:28 - 00:47:57)
Das heißt, ihr würd mir dann in der Datenbank das Ganze nochmal abspeichern. Mach ich wahrscheinlich sowieso, weil ich ja irgendwie loggen will, wann diese E-Mail ausgesendet wurde oder damit ich irgendwelche Statistiken habe, auch wie viele E-Mails ausgesendet wurden. dann würde ich das nochmal in der Datenbank abspeichern und der Consumer fragt da ab, ist das schon lockt da, wurde das schon ausgesendet und wenn das schon passiert ist, ignoriere das ganze. Aber das klingt schon sophisticated, also ich bin mir nicht sicher, ob das Newsletter Worker wirklich in der Realität auch so machen.
Andy Grunwald (00:47:57 - 00:48:12)
Das weiß ich nicht. Ich habe noch nie ein Newsletter-System selbst geschrieben. Und da ist auch die nächste Frage, ob du sowas selbst schreiben solltest oder nicht einfach einen Service nehmen solltest wie Cleverreach, Mailchimp, Amazon, Schießmichtod, Newsletter-Service, keine Ahnung.
Wolfi Gassler (00:48:12 - 00:48:23)
Ja, da geht es ja dann auch mehr um das E-Mail-Versenden. Das ist eigentlich die Kunst, das so zu versenden, dass es nicht im Spam-Folder landet. Also da geht es ja weniger um die Message-Queues, sondern mehr um das Versenden selbst.
Andy Grunwald (00:48:23 - 00:49:09)
Ja, aber unten drunter werden die halt schon ein ähnliches System haben. Weil auch die werden das natürlich nicht alles in einem Request-Response-Behavior abfeiern. Was natürlich auch noch ein Riesenvorteil von RabbitMQ ist, wir hatten vorhin darüber gesprochen, dass die AMQP supporten als Protokoll. Die einzelnen MQ-Server haben natürlich ein Interesse, mehrere Protokolle zu supporten, um natürlich ihre Anwendungsfälle ein bisschen breiter zu fächern. RabbitMQ selbst kann auch MQTT, die ganzen Leute, die sich ein bisschen mit Heimautomatisierung auseinandersetzen, werden da gegebenenfalls jetzt hellhörig, oder aber auch eine Connection via klassisch HTTP und Websockets, was natürlich dann auch recht interessant ist für die einfache Anbindung von existierenden Systemen.
Wolfi Gassler (00:49:10 - 00:49:45)
Das ist halt auch der Vorteil von so einem alten System, alt im positiven Sinne, was sich einfach über lange Zeit entwickelt hat, dass der Support von Protokollen gut ist, die Dokumentation, du findest viele Informationen darüber, du bekommst Plugins, Integrationen von anderen Services, Monitoring zum Beispiel oder Authentifizierung. Die ganzen Dinge sind halt schon zigfach gelöst worden und das ist halt auch ein Vorteil, wenn man irgendwas einführen will, weil man da halt einfach guten Support hat. Einerseits auf der Dokumentationsseite, aber andererseits auch auf der Tooling-Seite rundherum in diesem ganzen Ecosystem.
Andy Grunwald (00:49:46 - 00:50:52)
Ich selbst nutze Revit MQ schon seit ein paar Jahren in recht vielen meiner Seitenprojekte und betreibe es in einem Docker-Container mit reingemountetem Storage und bin mega Fan. Ich kann Leute verstehen, die sagen i-bar, Revit MQ, Erlang, Riesenschiff. Ja, ist alles nicht falsch, aber wenn man einmal seinen Kopf um ordentliches Message Queueing, Routing, von Nachrichten, verschiedene Types von Exchanges, diese Art Notebalancer, die ich vorhin erwähnt habe, Priority Queues und Dead Letter Queues. Wenn man da einmal mal den Use Case verstanden hat, dann habe ich das Gefühl, ich habe einen Hammer für jeden Nagel irgendwie. Weil du kannst, also du willst nicht mehr ohne und es ist halt einfach so bequem. Du kannst halt einfach auf Knopfdruck deine Worker hoch und runter skalieren und einfach Lastspitzen abfeiern. Und das Tolle ist, du kannst sogar Metadaten pro Nachricht hinzufügen und das bedeutet, Ich weiß ganz genau, welche Nachricht von welcher App erstellt wurde, welcher Content-Type drin ist, JSON, XML oder ähnliches und kann natürlich durch zusätzliche Header noch so Sachen wie Tracing enablen, was natürlich dann fürs Debugging ein Traum ist.
Wolfi Gassler (00:50:52 - 00:51:54)
Okay, ich habe also gelernt, Streaming und Message Queues sind nicht dasselbe. Also Kafka ist nicht unbedingt ein Ersatz für RabbitMQ. Wenn ich es einfacher haben will, ZeroMQ ist eine gute Anlaufstelle oder eines der gehosteten Cloud-Varianten, SQS, PubSub. Aber gibt es auch sicher viel kleinere noch. Man muss ja nicht immer nur die großen verwenden. Ist dann meistens auch kostengünstiger. Aber ich habe auch gelernt, dass der Andi gar nicht so negativ gegenüber den eigenen Implementierungen in der eigenen Datenbank steht. Ich persönlich sehe da schon wieder ganz viele Probleme bei einer eigenen Implementierung in der Datenbank. Also ich persönlich, wenn es irgendwie geht, würde eher auf sowas wie den Zero MQ setzen, weil ich mir einfach selber gar nicht diese Gedanken machen will, was da alles schief gehen könnte und das haben sich andere Leute überlegt und wie der Andi richtig gesagt hat, in dem ganzen Processing und Parallelität verstecken sich viele Hürden und Fallstricke, und denen möchte ich eigentlich gar nicht begegnen.
Andy Grunwald (00:51:54 - 00:52:12)
Ist, glaube ich, informationstechnisch recht interessant, solche Probleme zu lösen. Also, falls ihr mal eine Herausforderung haben wollt, setzt euch doch mal einen Abend hin oder ein ganzes Wochenende und versucht mal so was wie Exactly Once Delivery ordentlich zu implementieren. Da haben sich sehr, sehr viele Programmierer bereits die Zähne und die Haare ausgebissen und ausgerissen.
Wolfi Gassler (00:52:12 - 00:52:31)
Können wir ja mal eine eigene Episode darüber machen, weil mich interessieren diese Themen ja brennend, auch mit meinem Datenbank-Background, aber sie interessieren mich nicht, wenn ich am Wochenende irgendwo chill und das System einfach funktionieren muss. Und wenn ich das selber programmiert habe, dann wird es halt meistens genau dann nicht funktionieren, wenn ich eigentlich meine Ruhe haben will.
Andy Grunwald (00:52:31 - 00:53:11)
Lasst uns doch mal wissen, welchen Anwendungsfall ihr mit Message Queueing oder sogar Streaming abgedeckt habt. Vielleicht etwas kurioses dabei wie die Kommunikation oder das Update von Leaderboards bei Massive Multiplayer Online Games oder irgendwie das Rauspuschen von Fußballergebnissen während der WM. Mich würde es interessieren, was ihr so alles abgedeckt habt. und welche Message Queue Systeme ihr so im Einsatz habt. So ein Schiff wie RabbitMQ, irgendeine gehostete Lösung oder vielleicht auch die ganz klassische Implementierung von ich habe eine Datenmarkttabelle, wie Wolfgang es bevorzugt. Gerne über Twitter an atengkiosk oder via E-Mail an stetisch at engineeringkiosk.dev Und lasst.
Wolfi Gassler (00:53:11 - 00:53:30)
Uns vielleicht auch wissen, wenn ihr irgendwelche Anbieter, kleinere Anbieter kennt, von coolen Message-Queuing-Systemen. Vielleicht können wir da auch eine kleine Liste zusammenstellen. Es interessiert sicher viele Leute, was es da denn für Alternativen gibt und welche junge Systeme wir da noch nicht auf dem Schirm haben. Und genießt euer Jahr 2023! Tschö! Ciao!