Entkopplung einzelner Anwendungen in Event-driven-Architekturen

Event-driven-Architekturen mit Java: Vor- und Nachteile von Kafka und Kinesis

Sascha Möllering

©Shutterstock/bonumopus

Event-driven-Architekturen sind kein neues Architektur-Pattern, haben aber – unter anderem durch das Reactive Manifesto – wieder mehr Aufmerksamkeit erfahren. Der Erfolg von LinkedIn, die stetig wachsende Verbreitung von elastischen Ansätzen in der Cloud und immer stärker zunehmende Datenmengen lassen diese Form der Architektur wieder interessanter werden. Doch wie genau kann so etwas mit modernen Komponenten implementiert werden?

Der Vorteil von Event-driven-Architekturen besteht in der Entkopplung einzelner Anwendungen durch ein Message-System. Im Falle von LinkedIn wird Apache Kafka [1] als Message Bus für die Entkopplung genutzt. Kafka ist ein System, das auf dem Publish-/Subscribe-Paradigma basiert. Die Besonderheit von Kafka besteht in der Kombination aus Queueing und der Persistierung von Nachrichten. Man kann es sich als Commit Log vorstellen, das über mehrere Server in einem Cluster verteilt ist. Die Nachrichten werden in Topics und Partitions organisiert, wobei ein Topic aus mehreren Partitionen bestehen kann. Jedes Topic kann mehrere Publisher (Produzenten) und Subscriber (Konsumenten) unterstützten. Die Nachrichten innerhalb eines Topics werden innerhalb des Kafka-Clusters nach folgenden Regeln vorgehalten:

  • für eine bestimmte Zeitspanne
  • die Gesamtanzahl von Nachrichten pro Partition
  • für einen bestimmten Key innerhalb einer Nachricht nur die neuesten Nachrichten

Jede Kafka-Partition ist eine geordnete, unveränderliche Sequenz von Nachrichten, in die neue Nachrichten mit der Zeit hinzugefügt werden. Den Nachrichten in einer Partition wird eine eindeutige (sequenzielle) ID zugewiesen, die „Offset“ genannt wird und jede Nachricht innerhalb der Partition eindeutig identifiziert. Im Gegensatz zu anderen Messaging-Systemen müssen sich die Konsumenten selbst um die Verwaltung des Offsets kümmern, was aber auch einen großen Vorteil mit sich bringt: Normalerweise würde ein Konsument den Offset linear immer weiter schieben, um eine Nachricht nach der anderen zu lesen. In diesem Fall kann aber der Offset bewegt und somit die Nachrichten in jeder beliebigen Reihenfolge gelesen werden. Durch diese Logik können beispielsweise Nachrichten mehrfach gelesen werden, falls ein „replay“ von Nachrichten notwendig ist. Der Offset wird dabei in Apache Zookeeper [2] abgelegt. Zookeeper ist ein zentraler Service, in dem Konfigurationen abgelegt werden können. Damit bietet sich die Software als zentraler Bestandteil einer verteilten Architektur an.

DevOpsCon Whitepaper 2018

Free: BRAND NEW DevOps Whitepaper 2018

Learn about Containers,Continuous Delivery, DevOps Culture, Cloud Platforms & Security with articles by experts like Michiel Rook, Christoph Engelbert, Scott Sanders and many more.

Amazon Web Services bietet mit Amazon Kinesis [3] einen ähnlichen Service an, der vollständig verwaltet wird. Bei Kinesis werden die Nachrichten in Streams und Shards organisiert, Streams entsprechen den Topics, Shards den Partitions. Auch bei Kinesis muss der Offset selbst verwaltet werden, Amazon bietet aber mit der so genannten Kinesis Client Library (KCL [4]) eine Bibliothek, die dieses – und viele andere nützliche Features darüber hinaus – für den Entwickler übernimmt. Im Gegensatz zu Kafka wird die Information über den Offset in einer DynamoDB-Tabelle abgelegt, die – falls nicht vorhanden – über KCL angelegt wird. Da Kinesis ein von Amazon verwalteter Service ist, existieren gewisse Restriktionen:

  • die Daten werden maximal 24 Stunden vorgehalten
  • der Payload darf nur 1 MB groß sein (vor dem Base64 Encoding)
  • aus jedem Shard können 2 MB pro Sekunde gelesen werden
  • in jedes Shard können 1 000 Nachrichten pro Sekunde und max. 1 MB geschrieben werden

Aufgrund der dargestellten Restriktionen ist es ratsam, ein Datenformat wie beispielsweise Protocol Buffer [5] oder Thrift [6] zu nutzen, um die Größe der Nachrichten möglichst gering zu halten. Auf die Daten aus den Streams kann mithilfe des AWS SDKs für Java [7] zugegriffen werden. Wie bereits angedeutet, ist es empfehlenswert, für das Lesen der Daten die KCL zu nutzen, die die Verwaltung der Metadaten vollständig übernimmt. Deutlich einfacher als mit dem SDK und der KCL, ist die Verwendung des Services AWS Lambda [8], bei dem eigener Code beim Auftreten eines bestimmten Events ausgeführt wird. Bis vor Kurzem hat Lambda nur JavaScript unterstützt, glücklicherweise ist Java 8 als unterstützte Plattform hinzugekommen. Lambda scheint ein Service mit viel Potenzial zu sein, speziell das Zusammenspiel von Kinesis und Lambda ist außerordentlich interessant: Lambda implementiert sowohl ein Push- als auch ein Pull-Modell, wobei Letzteres in diesem Kontext interessant ist. Eine Lambda-Funktion kann auf Events aus einem Kinesis-Stream reagieren, die Implementierung eines Kinesis Consumers besteht aus erstaunlich wenigen Zeilen Code:

public class KinesisConsumer {
  public void recordHandler(KinesisEvent event) throws IOException {
    for (KinesisEventRecord rec : event.getRecords()) {
      ByteBuffer data = rec.getKinesis().getData();
    }
  }
}

Das ist ein vollständiger Kinesis Consumer, der automatisiert skaliert und pro Event abgerechnet wird. Es ist nicht notwendig, eigene EC2-Instanzen aufzusetzen und diese zu skalieren; man kann sich vollständig auf die Implementierung der eigentlichen Businesslogik konzentrieren.

Kafka und Kinesis sind zwei sehr interessante Infrastrukturkomponenten für die Implementierung einer Event-driven-Architektur. Die hohe Flexibilität und die enorme Skalierbarkeit gehen aber mit einer zusätzlich erhöhten Komplexität einher: Das Schreiben von Nachrichten ist in beiden Systemen sehr einfach, das Lesen hingegen erfordert zusätzlichen Verwaltungsaufwand für den Offset.

Aufmacherbild: Architecture assembling concept von Shutterstock / Urheberrecht: bonumopus

Geschrieben von
Sascha Möllering
Sascha Möllering
Sascha Möllering arbeitet als Solutions Architect bei der Amazon Web Services Germany GmbH. Seine Interessen liegen in den Bereichen Automation, Infrastructure as Code, Distributed Computing, Container und JVM.
Kommentare

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
4000
  Subscribe  
Benachrichtige mich zu: