README.md 21.7 KB
Newer Older
Nane Kratzke's avatar
Nane Kratzke committed
1
# Lab 10: Messaging-basierte Interaktion
Nane Kratzke's avatar
Nane Kratzke committed
2

Nane Kratzke's avatar
Nane Kratzke committed
3
Wir werden in diesem Lab Messaging überaschenderweise am Beispiel einer Datenbank -- [Redis](https://redis.io) -- demonstrieren. Wir nutzen Redis vor allem deswegen, weil es sehr einfach zu deployen ist und bereits an anderen Stellen in Labs verwendet wurde und wir so den Technologiestack übersichtlich und die Komplexität überschaubar halten können. Redis wurde zwar primär als In-Memory Key-Value Datenbank entwickelt, hat jedoch mittlerweile sowohl Publish-Subscribe als auch Queueing Features erhalten, die für einfache Anwendungsfälle durchaus ausreichend sind. Als Messaging-Komponenten werden in Cloud-nativen Systemen häufig "klassische" Lösungen wie bspw. [Kafka](https://kafka.apache.org), [Nats](https://nats.io), [RabbitMQ](https://www.rabbitmq.com), [ActiveMQ](https://activemq.apache.org) und weitere [AMQP](https://www.amqp.org)- oder [MQTT](https://mqtt.org)-konforme Lösungen verwendet.
Nane Kratzke's avatar
Nane Kratzke committed
4
5

Die in diesem Lab am Beispiel von Redis vermittelten Prinzipien sind aber durchaus auf diese Systeme übertragbar, da die zu Grunde liegenden Kommunikationsmuster Publish-Subscribe und Queueing letztlich von all diesen Messaging-Systemen ermöglicht werden.
Nane Kratzke's avatar
Nane Kratzke committed
6
7
8
9
10
11
12

## Inhalt

- [Lab 10: Messaging-basierte Interaktion](#lab-10-messaging-basierte-interaktion)
  - [Inhalt](#inhalt)
  - [Vorbereitung](#vorbereitung)
  - [Übung 01: Pub/Sub Messaging (Fan Out)](#übung-01-pubsub-messaging-fan-out)
Nane Kratzke's avatar
Nane Kratzke committed
13
14
15
  - [Übung 02: Persistentes Pub/Sub Messaging](#übung-02-persistentes-pubsub-messaging)
  - [Übung 03: Event Sourcing](#übung-03-event-sourcing)
  - [Übung 04: Queueing](#übung-04-queueing)
Nane Kratzke's avatar
Nane Kratzke committed
16
17
18
19
20
21
  - [Verständnis- und Transferfragen](#verständnis--und-transferfragen)
  - [Links](#links)
  - [Was sollten Sie mitnehmen](#was-sollten-sie-mitnehmen)

## Vorbereitung

Nane Kratzke's avatar
Nane Kratzke committed
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Sie benötigen auf Ihren lokalen Entwicklungsrechner:

- [Python 3](https://www.python.org/downloads)
- [Docker](https://www.docker.com/get-started)
- [Lens](https://k8slens.io)

Führen Sie anschließend bitte folgende Schritte aus:

1. [Forken](https://git.mylab.th-luebeck.de/cloud-native/lab-rest/-/forks/new) Sie bitte dieses GitLab-Repository in Ihren GitLab-Namensraum.
2. Klonen Sie das in Schritt 1 geforkte Repository bitte anschließend auf ihrem lokalen Rechner (`git clone`).
3. Installieren Sie anschließend bitte lokal auf Ihrem Rechner die Kubernetes-IDE [Lens](https://k8slens.dev/).
4. Laden Sie sich Ihre `kubeconfig` Datei im [Moodle-Kurs](https://to-be-donex) herunter.
5. Starten Sie Lens und fügen Sie der IDE die kubeconfig Datei hinzu, um auf Ihren Cluster zugreifen zu können. Sie sollten dann Ihren Namespace in dem für Sie bereitgestellten K8S-Cluster sehen.
6. Erstellen Sie anschließend in Gitlab unter `Einstellungen -> Repository -> Bereitstellungstoken` für das in Schritt 1 geforkte Repository einen Bereitstellungstoken, um selbstgebaute Container Images deployen zu können.
    - **Name:** `Registry read access (deployment)`
    - **Username:** `image-registry` (bitte exakt so!)
    - **Scope:** `read-registry` (nicht mit read repository verwechseln!)
    - Klicken Sie anschließend auf Bereitstellungstoken erstellen und kopieren Sie sich dieses geheime Token in die Zwischenablage!
7. Hinterlegen Sie nun für Gitlab Build-Pipelines dieses geheime Token unter `Einstellungen -> CI/CD -> Variables (Aufklappen) -> ADD VARIABLE` als CI/CD-Variable.
    - **Key:** `CI_REGISTRY_TOKEN` (exakt so)
    - **Value:** Fügen Sie hier das geheime Token (Schritt 2) aus der Zwischenablage ein.
    - **Type:** `Variable` (nichts anderes)
    - **Flags:** Selektieren Sie `Mask Variable` damit das geheime Token in Log-Dateien maskiert wird.
8. Hinterlegen Sie in Ihrem geforkten GitLab-Repository nun die `kubeconfig`-Datei als CI-Environment-Variable mittels `Einstellungen -> CI/CI -> Variables (Aufklappen) -> ADD VARIABLE` (setzen Sie hierfür folgende Werte)
    - **Key:** `KUBECONFIG` (Exakt so eingeben)
    - **Value:** Inhalt der kubeconfig (z.B. mittels Copy-Paste aus Editor)
    - **Typ:** `File` (Auswählen, WICHTIG!!!)
9. Öffnen Sie Lens und hinterlegen Sie mittels `+` die `kubeconfig`-Datei, die Sie auch im vorherigen Schritt in der Deployment Pipeline hinterlegt haben.

Nane Kratzke's avatar
Nane Kratzke committed
51
52
## Übung 01: Pub/Sub Messaging (Fan Out)

Nane Kratzke's avatar
Nane Kratzke committed
53
54
In dieser Übung werden wir uns folgenden Publish-Subscribe Kommunikationsmuster widmen.

Nane Kratzke's avatar
Nane Kratzke committed
55
56
57
58
59
60
61
62
```
              +--M3,M2,M1-> C
              |
P --M3,M2,M1--+--M3,M2,M1-> C
              |
              +--M3,M2,M1-> C
```

Nane Kratzke's avatar
Nane Kratzke committed
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
Ein Producer *P* erzeugt Messages, die in einen Channel einer Message Queue gegeben werden (Publish). Diese Queue
verteilt dann alle Messages an Consumer *C*, die sich für diesen Channel angemeldet haben (Subscribe). Auf diese Weise erhalten alle Consumer alle Messages, ohne dass Producer die Empfänger kennen muss. Die Message Queue entkoppelt so Producer von Consumer und umgekehrt.

- Studieren Sie bitte sowie den [Publish/Subscribe Abschnitt](https://github.com/andymccurdy/redis-py#publish--subscribe) der Redis Python API.
- Versuchen Sie nun die beiden Dateien `messaging/pubsub-producer.py` und `messaging/pubsub-consumer.py` nachzuvollziehen.
- Versuchen Sie nun die `.gitlab-ci.yaml` sowie die Kubernetes Manifests im Ordner `deploy` nachzuvollziehen. Die Deployment Pipeline dieses Labs erzeugt eine Redis Datenbank in Ihrem Kubernetes Namespace und sieht diverse manuell triggerbare Jobs für unterschiedliche Consumer und Producer vor, um Teile dieses Labs zu starten.
- Triggern Sie nun diese Pipeline (bspw. durch einen Commit dieses Repos).
- Wenn die Redis Datenbank erfolgreich in Kubernetes läuft (checken Sie dies in Lens), wechseln Sie in Gitlab in die Pipelines Ansicht (`CI/CD -> Pipelines` -> auf letzte bestandene Pipeline klicken) und starten Sie manuell die beiden Jobs `pubsub-consumer` und `pubsub-producer` in der Web-Oberfläche (Play Buttons der Jobs).
- Im Lens Terminal (oder der Oberfläche sollten Sie nun drei Pods sehen)
  ```Bash
  > kubectl get pods
  NAME                               READY   STATUS    RESTARTS   AGE
  redis-599f4cc796-6pltl             1/1     Running   0          25m
  pubsub-consumer-b9756d886-62z8l    1/1     Running   0          19m
  pubsub-producer-79bcdbf9d8-bdxrn   1/1     Running   0          19m
  ```
- Sehen Sie sich in Lens nun die Logs des Producers an:
  ```
  ...
  Publishing message 'Hi, this is message #4317 from pubsub-producer-79bcdbf9d8-bdxrn.' to channel 'xpubsub'
  Publishing message 'Hi, this is message #4318 from pubsub-producer-79bcdbf9d8-bdxrn.' to channel 'xpubsub'
  Publishing message 'Hi, this is message #4319 from pubsub-producer-79bcdbf9d8-bdxrn.' to channel 'xpubsub'
  Publishing message 'Hi, this is message #4320 from pubsub-producer-79bcdbf9d8-bdxrn.' to channel 'xpubsub'
  Publishing message 'Hi, this is message #4321 from pubsub-producer-79bcdbf9d8-bdxrn.' to channel 'xpubsub'
  ```
- Die Logs des Consumers sollten in etwa so aussehen:
  ```
  ...
  0.92ms | msg: {"timestamp": 1614764396330193114, "message": "Hi, this is message #4689 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.64ms | msg: {"timestamp": 1614764396731672144, "message": "Hi, this is message #4690 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.79ms | msg: {"timestamp": 1614764397232874681, "message": "Hi, this is message #4691 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.79ms | msg: {"timestamp": 1614764397734203948, "message": "Hi, this is message #4692 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.81ms | msg: {"timestamp": 1614764398035370260, "message": "Hi, this is message #4693 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.52ms | msg: {"timestamp": 1614764398236610874, "message": "Hi, this is message #4694 from pubsub-producer-79bcdbf9d8-bdxrn."}
  0.70ms | msg: {"timestamp": 1614764398737878344, "message": "Hi, this is message #4695 from pubsub-producer-79bcdbf9d8-bdxrn."}
  ```
  Die Zeitangaben in ms geben an, wie lange eine Message vom Producer zum Consumer benötigt hat (Latenz). Vergleichen Sie diese Werte mit den Werten, die Sie im letzten Lab zu REST und gRPC basierten Interaktionsverfahren erhoben haben.
- Merken Sie sich in etwa die letzte Messagenummer, die der Consumer bis dahin erhalten hat. Löschen Sie dann in Lens  den Consumer und warten Sie ab, bis der Pod wieder durch Kubernetes automatisch neu gestartet wurde. Prüfen Sie im neuen Container Log des regenerierten Pods ab welcher Message Nummer dieser das Streaming wieder auf nimmt?
- Löschen Sie nun das Producer Deployment in Lens, so dass kein neuer Producer Pod gestartet wird? Laufen noch weitere Messages im Consumer auf? Stürzt der Consumer ab?
- Deployen Sie in Gitlab mittels des manuellen Pipeline Jobs erneut den Producer (Play Button des Jobs).
- Der Producer sollte wieder ab 1 nummerierte Messages erzeugen, die der Consumer im Log anzeigt.
- Skalieren Sie nun in Lens den Producer auf 3 Instanzen hoch (`Producer Deployment -> Scale`). Achten Sie nun im Consumer Log auf die Ursprünge der Messages. Sie erhalten nun Messages von mehreren Producern.
  ```
  0.89ms | msg: {"timestamp": 1614765108327074527, "message": "Hi, this is message #95 from pubsub-producer-79bcdbf9d8-ch4w9."}
  1.10ms | msg: {"timestamp": 1614765108467772402, "message": "Hi, this is message #610 from pubsub-producer-79bcdbf9d8-lc2rq."}
  0.78ms | msg: {"timestamp": 1614765108746772325, "message": "Hi, this is message #100 from pubsub-producer-79bcdbf9d8-nzr2v."}
  0.86ms | msg: {"timestamp": 1614765108828138961, "message": "Hi, this is message #96 from pubsub-producer-79bcdbf9d8-ch4w9."}
  0.81ms | msg: {"timestamp": 1614765108869005443, "message": "Hi, this is message #611 from pubsub-producer-79bcdbf9d8-lc2rq."}
  ```
- Skalieren Sie auch die Consumer auf drei Instanzen hoch. Vergleichen Sie die Logs der drei Pods in Lens. Laufen unterschiedliche Messages auf?
- Löschen Sie nun das Producer Deployment und das Consumer Deployment (entweder in Lens oder mit dem Gitlab Pipeline `pubsub`-Job in der `terminate`-Stage).

Diese Übung hat nicht persistentes PubSub-Messaging mittels Redis demonstriert. Sie haben gesehen, dass Sie sowohl Consumer wie auch Producer unabhängig von einander hoch- und herunterskalieren können. Sie haben allerdings auch gesehen, dass diese Form des Messaging stateless ist. Messages, die einmal verschickt wurden, werden von Redis vergessen. Wenn Sie Anwendungsfälle haben, in denen die Historie von Events wichtig ist, weil Sie ggf. wieder abgespielt werden müssen (z.B. um eine Datenbank zu rekonstruieren), benötigen wir persistente Messaging Systeme.

Als Datenbank, kann Redis dies natürlich auch.
  
Nane Kratzke's avatar
Nane Kratzke committed
119
120
## Übung 02: Persistentes Pub/Sub Messaging

Nane Kratzke's avatar
Nane Kratzke committed
121
122
123
Diese Übung zeigt Ihnen wie man Redis als persistentes Messaging System einsetzen kann. Wir nutzen hierfür das `xadd`-[Command](https://redis.io/commands/XADD) (Producer) von Redis mit dem Redis Event Streams aufbauen kann. Mittels des `xread`-[Commands](https://redis.io/commands/XREAD) lässt sich aus solchen Streams lesen (Consumer).

- Lesen Sie sich hierzu als erstes ein wenig in [Redis Streams](https://redis.io/topics/streams-intro) ein.
124
- Studieren Sie anschließend die Klasse `messaging/MQueue.py`. Hier ist Ihnen eine Wrapper-Klasse um Redis gegeben, die die Commands `xadd`, `xread` und `xgroupread` so kapselt, dass diese komfortabel mittels einer `listen()`-Methode für Consumer und mittels einer `publish()`-Methode für Producer genutzt werden kann. *Auf `listen_as_group()` gehen wir in Übung 04 noch genauer ein.*
125
126
- Versuchen Sie nun die Dateien `messaging/queueing-producer.py` und `messaging/queueing-consumer.py` nachzuvollziehen, um zu verstehen, wie man die Klasse `MQueue` für ein Publish-Subscribe Pattern einsetzen kann.
- Starten Sie nun in Gitlab manuell die Jobs `queueing-consumer` und `queueing-producer` in der `deploy`-Stage um einen Consumer und einen Producer zu erzeugen.
Nane Kratzke's avatar
Nane Kratzke committed
127
128
129
130
131
132
- Warten Sie ab, bis beide Deployments erzeugt wurden (vollziehen Sie dies in Lens nach).
- Sehen Sie sich dann in Lens die Logs des Consumer Pods und die Logs des Producer Pods an. Sie sehen, das funktinioniert wie in Übung 01 auch.
- Löschen Sie nun das Consuming Deployment (es soll also wirklich kein Consuming Pod laufen). Warten Sie ein paar Minuten und merken Sie sich im Consumer in etwa die Message die zum Zeitpunkt des Löschens erzeugt wurde.
- Deployen Sie dann den Consumer in Gitlab erneut. Beobachten Sie nun in Lens das Verhalten im Pod Log des neuen Consumers. Sie werden feststellen, dass es im Consumer immer noch einen Gap bei den empfangenen Messages gibt. Die Messages während der Consumer down war, werden weiterhin nicht empfangen.

Was soll also der ganze Aufwand mit der Persistierung von Message Streams?
Nane Kratzke's avatar
Nane Kratzke committed
133

Nane Kratzke's avatar
Nane Kratzke committed
134
135
## Übung 03: Event Sourcing

Nane Kratzke's avatar
Nane Kratzke committed
136
137
138
139
140
141
142
143
144
145
146
Messaging Systeme werden normalerweise so eingesetzt, dass Consumer ab dem Zeitpunkt auf Events lauschen, ab dem Sie gestartet wurden. Man verfolgt also normalerweise Messages in (naher) Echtzeit und ist nicht an Events der Vergangenheit interessiert. Es kann aber durchaus sinnvoll sein, auch Events der Vergangenheit zu verarbeiten. Z.B. weil eine Teilkomponenten down war (ggf. sogar mehrere Stunden). Dann wäre es schön, wenn man dieses "Backlog" wieder aufarbeiten könnte, einfach indem man die Events noch einmal ablaufen lässt. Dies ist -- vereinfacht ausgedrückt -- [Event Sourcing](http://martinfowler.com/eaaDev/EventSourcing.html) (vgl. auch [Wikipedia](https://de.wikipedia.org/wiki/Event_Sourcing)).

Man kann persistenten Messaging Systemen normalerweise mitteilen, ab welchem Zeitpunkt Events abgerufen werden sollen. Unsere Wrapper-Klasse sieht hierzu den `since`-Parameter vor.

Ergänzen Sie nun in der `messaging/queueing-consumer.py` diesen `since`-Parameter.

```Python
for since, msg in queue.listen(since=0):
    print(msg)
```

Nane Kratzke's avatar
Nane Kratzke committed
147
Committen Sie diese Änderung in das Repo und deployen Sie dann den Consumer mittels der Gitlab Pipeline erneut. Beobachten Sie nun in Lens das Verhalten im Pod Log des neuen Consumers. Sie sollten feststellen, dass einige Messages sehr schnell einfliegen, und sich dann irgendwann des Tempo verlangsamt. Woher kommt das? Es werden nun alle Messages abgerufen (seit Anbeginn der Queue). In Übung 01 wären diese Messages einfach "verschwunden".
Nane Kratzke's avatar
Nane Kratzke committed
148

149
150
151
152
153
154
155
156
157
158
Sie können auch ab einem beliebigen Zeitpunkt aufsetzen. Schauen Sie doch einfach in Ihr Log des Consumers, um sich einen beliebigen Aufsetzpunkt zu wählen.

```
15331.28ms | msg b'1614769654088-0': {'text': 'Hi, this is message #625 from queueing-producer-64b575bb98-wssf2.'}
10327.25ms | msg b'1614769659092-0': {'text': 'Hi, this is message #626 from queueing-producer-64b575bb98-wssf2.'}
6322.52ms | msg b'1614769663096-0': {'text': 'Hi, this is message #627 from queueing-producer-64b575bb98-wssf2.'}
5320.72ms | msg b'1614769664098-0': {'text': 'Hi, this is message #628 from queueing-producer-64b575bb98-wssf2.'}
1319.34ms | msg b'1614769668100-0': {'text': 'Hi, this is message #629 from queueing-producer-64b575bb98-wssf2.'}
```

Nane Kratzke's avatar
Nane Kratzke committed
159
Um z.B. ab der Message `#628` weiter zu lesen, könnten dann folgendes eingeben:
160
161
162
163
164
165
166

```Python
for since, msg in queue.listen(since=1614769663096):
    print(msg)
```

Committen Sie, pushen Sie in die Gitlab Pipeline und redeployen anschließend den Consumer erneut. Sie werden feststellen, die Logs setzen ab Message `#628` fort.
Nane Kratzke's avatar
Nane Kratzke committed
167

Nane Kratzke's avatar
Nane Kratzke committed
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
```
queueing-consumer-66cc6f8cfb-v55w8 has found already existing consumer group for xqueue
594444.00ms | msg b'1614769664098-0': {'text': 'Hi, this is message #628 from queueing-producer-64b575bb98-wssf2.'}
590442.67ms | msg b'1614769668100-0': {'text': 'Hi, this is message #629 from queueing-producer-64b575bb98-wssf2.'}
588439.98ms | msg b'1614769670102-0': {'text': 'Hi, this is message #630 from queueing-producer-64b575bb98-wssf2.'}
583434.14ms | msg b'1614769675108-0': {'text': 'Hi, this is message #631 from queueing-producer-64b575bb98-wssf2.'}
581431.20ms | msg b'1614769677111-0': {'text': 'Hi, this is message #632 from queueing-producer-64b575bb98-wssf2.'}
579428.24ms | msg b'1614769679114-0': {'text': 'Hi, this is message #633 from queueing-producer-64b575bb98-wssf2.'}
...
```

__Transferaufgabe:__

- Schreiben Sie den Consumer so um, dass er sich den Zeitpunkt der letzten von Ihm verarbeiteten Nachricht merkt (Achtung Stateful! Sie brauchen dann wohl ein Volume oder Sie speichern sich dies in Redis selber!), damit er bei einem Restart an exakt dieser Stelle mit der Verarbeitung des Event Streams fortsetzen kann.
- Passen Sie ggf. die Deployment Pipeline und das Deployment Manifest an (falls Sie ein Volume nutzen wollen).

Sie können auch gerne mehrere Consumer starten. Sie werden feststellen, dass diese alle ab derselben Stelle mit der Bearbeitung fortsetzen werden. D.h. die Messages gehen immer noch wie in Übung 01 und 02 an alle Consumer.

Was können wir machen, damit Messages über mehrere Consumer gleichmäßig verteilt werden, um Arbeit über mehrere Instanzen verteilen zu können?

Nane Kratzke's avatar
Nane Kratzke committed
188
## Übung 04: Queueing
Nane Kratzke's avatar
Nane Kratzke committed
189

Nane Kratzke's avatar
Nane Kratzke committed
190
191
Beim Queueing Kommunikationsmuster erzeugt ein Producer *P* Messages, die wie gehabt in einen Channel einer Message Queue gegeben werden (Publish). Diese Queue verteilt dann allerdings alle Messages an mehrere Consumer *C1, C2, C3, ..* einer Gruppe, die sich für diesen Channel angemeldet haben (Subscribe). So gehen nicht alle Messages an alle Consumer, sondern werden innerhalb der Gruppe verteilt. Weiterhin müssen sich die Consumer untereinander nicht kennen und der Producer die Consumer ebenfalls nicht.

Nane Kratzke's avatar
Nane Kratzke committed
192
```
Nane Kratzke's avatar
Nane Kratzke committed
193
                 +--M4,M1-> C1
Nane Kratzke's avatar
Nane Kratzke committed
194
                 |
Nane Kratzke's avatar
Nane Kratzke committed
195
P --M4,M3,M2,M1--+-----M2-> C2
Nane Kratzke's avatar
Nane Kratzke committed
196
                 |
Nane Kratzke's avatar
Nane Kratzke committed
197
                 +-----M3-> C3
Nane Kratzke's avatar
Nane Kratzke committed
198
199
```

Nane Kratzke's avatar
Nane Kratzke committed
200
201
202
203
204
205
206
207
208
209
210
211
212
Messaging Systeme benötigen hierfür zusätzlich die Information welche Consumer sich zu einer Gruppe zusammenfinden. Für die Subscription ist also auf Seiten des Consumers zusätzlich die Angabe einer Gruppe erforderlich, damit das Messaging System Messages innerhalb der Gruppe auch verteilen kann.

Um dies auszuprobieren, können Sie in der `messaging/queueing-consumer.py` die `listen_as_group()`-Methode nutzen.

```Python
for since, msg in queue.listen_as_group("consumers"):
    print(msg)
```

Committen Sie diese Änderung in das Repo und deployen Sie dann den Consumer mittels der Gitlab Pipeline erneut. Beobachten Sie nun in Lens das Verhalten im Pod Log des neuen Consumers. Auf den ersten Blick werden Sie keine Änderung feststellen. Das Verhalten des Consumers ist wie in Übung 02.



Nane Kratzke's avatar
Nane Kratzke committed
213
214
## Verständnis- und Transferfragen

Nane Kratzke's avatar
Nane Kratzke committed
215
216
- Für welche Anwendungsfälle würden Sie das PubSub-Kommunikationsmuster einsetzen?
- Für welche Anwendungsfälle würden Sie das Queueing-Kommunikationsmuster einsetzen?
Nane Kratzke's avatar
Nane Kratzke committed
217
218
- Welche Vor- und Nachteile hat die Persistierung von Message Queues?
- Erklären Sie Event Sourcing in eigenen Worten.
Nane Kratzke's avatar
Nane Kratzke committed
219
220
221
222
223
224
225
226
227
- Vergleichen Sie die Latenzzeiten bei PubSub und Queue? Gibt es nennenswerte Unterschiede?
- Vergleichen Sie die Latenzzeiten dieses Labs mit dem gRPC-Lab? Welche Technologie ist grundsätzlich performanter? Woher kommt das?
- Wie stufen Sie den Grad der Kopplung bei Messaging/Streaming im Vergleich zu gRPC ein?
- Wie stufen Sie den Grad der Kopplung bei Messaging/Streaming im Vergleich zu REST ein?
- Blicken wir nun auf die Labs zu REST, gRPC und Streaming zurück?
  - Vor dem Hintergrund loser Kopplung und Performanz:
  - In welchen Fällen würden Sie REST einsetzen?
  - In welchen Fällen würden Sie gRPC einsetzen?
  - In welchen Fällen würden Sie Messaging einsetzen?
Nane Kratzke's avatar
Nane Kratzke committed
228
229
230
231
232
233
234

## Links

- [Redis](https://redis.io)
- [Introduction to Redis Streams](https://redis.io/topics/streams-intro)
- Weitere Messaging Lösungen wie [Kafka](https://kafka.apache.org), [Nats](https://nats.io), [RabbitMQ](https://www.rabbitmq.com), [ActiveMQ](https://activemq.apache.org)
- Messaging Standards wie [AMQP](https://www.amqp.org) und [MQTT](https://mqtt.org)
Nane Kratzke's avatar
Nane Kratzke committed
235
236
- [Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html) (Martin Fowler)
- [Event Sourcing](https://de.wikipedia.org/wiki/Event_Sourcing) (Wikipedia)
Nane Kratzke's avatar
Nane Kratzke committed
237
238
239

## Was sollten Sie mitnehmen

Nane Kratzke's avatar
Nane Kratzke committed
240
- Obwohl Redis eigentlich eine In-Memory Key-Value Datenbank ist, kann Sie (für viele überraschend) auch für (einfaches) Messaging eingesetzt werden. Gegenüber komplexeren Lösungen wie bspw. Kafka kann dies durchaus von Vorteil sein.
Nane Kratzke's avatar
Nane Kratzke committed
241
- Das Kommunikationsmuster Publish-Subscribe kann für vor allem für Fan-Out Anwendungsfälle eingesetzt werden, d.h. bei der Nachrichten an ALLE Consumer gehen. Wenn Publish-Subscribe Messaging persistiert wird, kann es zum [Event Sourcing](https://de.wikipedia.org/wiki/Event_Sourcing) verwendet werden.
Nane Kratzke's avatar
Nane Kratzke committed
242
- Das Kommunikationsmuster Queueing wird vor allem für Load Balancing eingesetzt werden, bei der Nachrichten über mehrere Consumer zur Verarbeitung verteilt und dort verarbeitet werden müssen. Sowohl Producer als auch Consumer können dabei unabhängig von einander skaliert werden.
Nane Kratzke's avatar
Nane Kratzke committed
243
- Persistente Messaging Systeme können als Event Stores im Rahmen des Event Sourcings eingesetzt werden.
Nane Kratzke's avatar
Nane Kratzke committed
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
- Messaging ist hinsichtlich Übertragungslatenzen meist performanter als gRPC, gRPC ist üblicherweise performanter als REST.
- Sowohl REST als auch Messaging ermöglichen eine lose Kopplung von Services.
- Die bislang betrachteten Technologien kann man aufsteigend anhand des Grads Ihrer Kopplung ordnen:
  1. **Messaging** (Consumer und Producer gehen eine Kopplung zu einem Use Case agnostischen Message Broker ein)
  2. **REST** (Consuming Services gehen eine Kopplung zu einem Providing Service ein)
  3. **gRPC** (Consuming und Providing Service gehen eine gegenseitige Kopplung ein)

Eine abschließende Platzierung der betrachteten Ansätze könnte daher wie folgt aussehen:

| Technologie | Kopplung | Performanz | Broker  | Summe der Platzierungen | Kommunikationsmuster
|-------------|:--------:|:----------:|:------: |:------:|--------------------------
| REST        | 2        | 3          | nein (1)| **6** | Request-Response
| gRPC        | 3        | 2          | nein (1)| **6** | Request-Response
| Messaging   | 1        | 1          | ja (3)  | **5** | Publish-Subscribe + Queueing

Einen klaren Gewinner gibt es also nicht (ansonsten hätte sich dieser vermutlich auch schon durchgesetzt). Es kommt also (wie so häufig) auf den Use Case an.