So schöpfst du das volle Potenzial von CloudEvents

20.12.2023Ricky Elfner
Cloud Cloud native Amazon Web Services azure

banner

CloudEvents ist eine Open-Source-Initiative, die von der Serverless Working Group der CNCF ins Leben gerufen wurde. Die Arbeit an CloudEvents begann im Jahr 2017, und seitdem hat sich die Initiative zu einem bedeutenden Standard für den Austausch von Ereignissen zwischen Cloud-Anwendungen und -Diensten entwickelt. Die Idee hinter CloudEvents besteht darin, einen einheitlichen Standard für das Format und die Übertragung von Ereignissen zu schaffen, unabhängig von der zugrunde liegenden Technologie und Cloud-Plattform. Die Spezifikation wird kontinuierlich weiterentwickelt und verbessert, um sicherzustellen, dass sie den Bedürfnissen von Entwicklern und Unternehmen entspricht.

Da es sich um eine ziemlich bekannte Spezifikation handelt, wird diese bereits von verschiedenen namhaften Plattformen und Technologien genutzt, darunter Google Cloud’s Eventarc, das auf CloudEvents setzt, um eine nahtlose eventbasierte Kommunikation und Verarbeitung zu ermöglichen. Ebenso verwenden Open-Source-Projekte wie Knative CloudEvents, um Serverless Anwendungen sowie Workflows zu erstellen und zu orchestrieren. Zusätzlich hat auch Microsoft Azure CloudEvents in seine Event-Verarbeitungsdienste integriert, was die Zusammenarbeit und den Datenaustausch zwischen verschiedenen Cloud-Plattformen und -Services weiter verbessert. Dies unterstreicht die Relevanz und den weitreichenden Einsatz von CloudEvents als Standard zur Event-Datenbeschreibung in der Cloud-Landschaft.

image_01

Wenn man sich dieses Beispiel anhand eines IoT-Geräts anschaut, erkennt man sofort, dass hier einige Schritte zurückgelegt werden müssen, bis die Information in einem Data Lake oder bei einem Analysetool ankommt. Bei genauerer Betrachtung erkennt man auch verschiedene Protokolle. Das Umformen kostet jedes Mal Zeit und Rechenleistung. Um dies zu verhindern, wurde CloudEvents entwickelt, um eine standardisierte Struktur zur Verfügung zu stellen und dennoch unterschiedliche Protokolle zu verwenden.

Event-Definitionen

Definition von Eventgruppen

image_02

Mehrere Events können innerhalb einer Definitionsgruppe definiert werden. Bei einer Definition handelt es sich um ein Event. Wichtig sind hierbei die Attribute “id”, “description” und “format”. Anstelle des Formats “CloudEvent” kann alternativ eines der folgenden Formate verwendet werden: AMQP, MQTT, Protobuf, HTTP. Wenn ein Event zusätzliche Attribute benötigt, können diese über “attributes” definiert werden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    "definitionGroups": {
        "Contoso.CRM.Events": {
            "id": "Contoso.CRM.Events",
            "format": "CloudEvents/1.0",
            "definitions": {
                "Contoso.CRM.Events.CustomerCreated": {
                    "id": "Contoso.CRM.Events.CustomerCreated",
                    "description": "An order has been placed",
                    "format": "CloudEvents/1.0",
                    "metadata": {
                        "attributes": {
                            "id": {
                                "type": "string",
                                "required": true
                            },
                            "type": {
                                "type": "string",
                                "value": "Contoso.CRM.Events.CustomerCreated",
                                "required": true
                            },
                            "time": {
                                "type": "datetime",
                                "required": true
                            },
                            "source": {
                                "type": "uritemplate",
                                "value": "/crm/customers",
                                "required": true
                            }
                        }
                    },
                    "schemaFormat": "JSONSchema/draft-07",
                    "schemaUrl": "#/schemaGroups/Contoso.CRM.Events/schemas/customerCreatedEventData"
                },

            }
        }
    },

Endpoints

image_03

Endpoints sind Schlüsselkomponenten in der Welt der Cloud-Kommunikation und der Event-Verarbeitung. Sie fungieren als Schnittstellen bzw. “Ziele”, an denen Ereignisse erzeugt, gesendet oder empfangen werden. Endpoints stellen ein Superset von Definitionsgruppen dar und dienen als Erweiterung. Dadurch gibt es zusätzliche Attribute, die es ermöglichen, die Art und Weise der Interaktion mit CloudEvents detaillierter zu definieren.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
"endpoints": {
    "Contoso.CRM.Eventing.Http": {
        "id": "Contoso.CRM.Eventing.Http",
        "usage": "producer",
        "config": {
            "protocol": "HTTP",
            "strict": false,
            "endpoints": [
                "https://erpsystem.com/events"
            ]
        },
        "definitionGroups": [
            "#/definitionGroups/Contoso.CRM.Events"
        ],
        "format": "CloudEvents/1.0"
    }
}

Zu diesen Attributen gehören:

usage

Das usage Attribut gibt an, wie der Endpoint genutzt wird. Er kann dabei als Producer, Consumer oder Subscriber fungieren.

Event-Producer versenden Ereignisse an spezifische Endpunkte, ein Vorgang, der oft als Push-Modell bezeichnet wird. Beispiele hierfür sind das Veröffentlichen von Nachrichten in MQTT- oder AMQP-Topics, bei dem Ereignisse aktiv an abonnierte Topics gesendet werden. Ein weiteres Beispiel ist das Posten von Ereignissen an eine HTTP-Webhook, wodurch Informationen an vordefinierte URL-Endpunkte übermittelt werden. Dieses Push-Modell ist essenziell für die Echtzeitkommunikation und die Ereignisverarbeitung in technischen Anwendungen.

image_04

Event-Consumer konsumieren Ereignisse von verschiedenen Endpunkten. Dieser Vorgang wird gelegentlich als Pull-Modell bezeichnet, da die Konsumenten aktiv Ereignisse von den Quellen abrufen. Ein anschauliches Beispiel hierfür ist die Nutzung von Protokollen wie MQTT oder AMQP, bei denen Event-Consumer aktiv Nachrichten von den entsprechenden Endpunkten abrufen, um sie in Echtzeit zu verarbeiten. Eine weitere Herangehensweise ist das Polling mittels HTTP (GET), bei dem Event-Consumer in regelmäßigen Abständen die Endpunkte abfragen, um zu überprüfen, ob neue Ereignisse vorliegen. Dieses Vorgehen ist von entscheidender Bedeutung für die Implementierung von Echtzeitdaten in Anwendungen und die nahtlose Kommunikation zwischen verschiedenen Komponenten.

image_05

Ein Subscriber-Endpunkt stellt eine Subscriber-API zur Verfügung. Hierbei wird über den Subscriber definiert, welche Ereignisse an einen bestimmten Producer-Endpunkt gesendet werden sollen. Dieses Konzept ermöglicht die gezielte Auswahl und Übertragung von Ereignissen an gewünschte Empfänger und ist ein zentrales Element in der Verwaltung von Event-Streams und der Steuerung der Ereignisverarbeitung.

image_06

channel

Mit diesem Attribut können mehrere Endpunkte desselben Kanals miteinander in Beziehung gesetzt werden. Genauer gesagt wird die Zuordnung für einen Kanal definiert.image

definitionGroups

Endpoints können auf andere DefinitionGroups verweisen. Dies ermöglicht es, eine hierarchische Struktur von CloudEvents-Definitionen zu erstellen.

config

Dieses Attribut ermöglicht die Konfiguration von Konnektivitätseinstellungen.

CloudEvent Modi im Detail

Binary-Mode

Die Informationen über ein Ereignis werden im Message-Body selbst gespeichert. Dies hat den Vorteil, dass die Übertragung sehr effizient erfolgen kann, ohne dass eine Konvertierung notwendig ist. Dies ist besonders nützlich, wenn Empfänger nicht mit CloudEvents vertraut sind, da sie die Metadaten einfach ignorieren können.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
POST /event HTTP/1.0
Host: example.com
Content-Type: application/json
ce-specversion: 1.0
ce-type: com.bnova.item 
ce-source: http: //bonva.com/repo
ce-id: 610b6dd4-c85d-417b-b58f-3771e532
{
"action": "item",
"itemID": "31"

Structured-Mode

Im Structured-Mode werden CloudEvents als strukturierte Nachrichten übertragen, die ein bestimmtes Format wie JSON oder XML verwenden. Diese Nachrichten enthalten sowohl die Ereignisdaten als auch Metadaten, die zusätzliche Informationen über das Ereignis liefern. Dadurch kann der Empfänger detaillierte Informationen über das Ereignis erhalten und auf Basis dieser Informationen entsprechende Aktionen auszuführen. Allerdings ist die Übertragung im Structured-Mode im Vergleich zum Binary-Mode etwas langsamer, da das strukturierte Format mehr Overhead verursacht und dadurch mehr Daten übertragen werden müssen. Dieses CloudEvent Format, bestehend aus Ereignismetadaten und Daten innerhalb der Payload, ermöglicht eine einfache Weiterleitung desselben Ereignisses über mehrere Routing-Hops und Protokolle hinweg.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
"specversion": "1.0",
"type": "com.bnova.ittem",
"source": "http://bnova.com/repo",
"id": "610b6dd4-c85d-417b-b58f-3771e532",
"datacontenttype": "application/json",
"data"    "action": "item",
    "itemID": "31"
  }

Batch-Mode

Durch den Batch-Modus können mehrere CloudEvents in einer einzigen Nachricht übertragen werden, was die Anzahl der notwendigen Netzwerkverbindungen reduziert und somit eine effizientere Übertragung ermöglicht. Ein weiterer Vorteil besteht darin, dass die Ereignisse in der Nachricht unabhängig voneinander sein können und dennoch in einer einzigen Übertragung zusammengefasst werden können. Dadurch wird eine höhere Skalierbarkeit erzielt. Zusätzlich bietet der Batch-Modus die Möglichkeit, die Reihenfolge der Ereignisse in der Nachricht zu steuern und bei Bedarf einzelne Ereignisse erneut zu übertragen. Die einzelnen Ereignisse werden hierbei gemäss einem spezifischen Ereignisformat in einem einzigen Nachrichten-Body codiert, wobei es sich um “null” oder mehr Ereignisse handeln kann.

Allgemeine Informationen zur Nutzung von CloudEvents

Minimales Set benötigter Attribute

Das minimale Set an Daten wird context attributes genannt. Dieses ist notwendig, um das Event an die richtige Stelle zu senden.

Benötigt:

  • id –> Eindeutige Identifizierbarkeit mittels ID und Source
  • source –> URI-Reference / Quelle des Events
  • specversion –> Bestimmt die CloudEvent Version
  • type –> Bestimmt den Typ

Optional:

  • subject
  • time
  • datacontenttype
  • dataschema

Eine weitere Möglichkeit ist, die Spezifikation zu erweiteren, wodurch es möglich ist, einer Nachricht zusätzliche Attribute zu übergeben. Voraussetzung hierfür ist das einhalten der Namenskonvetion. Vorhandene Erweiterungen sind:

Die aktuellste Auflistung ist hier zu finden: https://github.com/cloudevents/spec/blob/main/cloudevents/documented-extensions.md.

Event Formate

Die Serialisierung des CloudEvents wird durch das Ereignisformat definiert, das unter anderem JSON, Protobuf, Avro und XML umfassen kann. Allerdings werden nicht alle Formate von jedem SDK unterstützt. JSON ist das am häufigsten unterstützte Format, während andere Formate wie Avro oder Protobuf in bestimmten SDKs möglicherweise nicht verfügbar sind. Zum Beispiel unterstützt das Javascript-SDK JSON, jedoch nicht Avro oder Protobuf.

Protokolle

Darüber hinaus wird durch Protokollbindungen definiert, wie das CloudEvent an ein Anwendungsprotokoll gebunden wird. Die unterstützten Protokolle umfassen HTTP, AMQP, Kafka, MQTT, NATS und WebSockets. Auch hier ist zu beachten, dass nicht alle Protokollbindungen in jedem SDK verfügbar sind.

SDKs

Um CloudEvents in verschiedenen Sprachen zu schreiben, sind die gängigsten SDKs vorhanden:

Anwendungsfälle

CloudEvents können in unterschiedlichen Technologie-Stacks Anwendung finden.

  • AWS Lambda: CloudEvents ist ein unterstütztes Format für Ereignisse, die von AWS Lambda ausgegeben werden. Dies bedeutet, dass Lambda-Funktionen CloudEvents ausgeben können, um Ereignisse an andere Dienste weiterzugeben.
  • Kubernetes: Kubernetes kann CloudEvents verwenden, um auf Clusterereignisse wie Skalierung oder Fehler zu reagieren.
  • Knative: Knative, eine Serverless Plattform, die auf Kubernetes aufbaut. Sie nutzt CloudEvents zur Beschreibung von Ereignissen in der Plattform.
  • Azure Event Grid: Azure Event Grid kann CloudEvents als ein unterstütztes Ereignisformat akzeptieren und ermöglicht es, Ereignisse zwischen verschiedenen Azure-Diensten zu vermitteln.
  • Apache Camel: Apache Camel, ein Open-Source-Integrationssystem. Es unterstützt CloudEvents in seiner neuesten Version, um die Zusammenspiel von Ereignissen zu verbessern, die durch verschiedene Systeme fliessen.

Schema Registry

image

Wenn man nun die gesamten Informationen als Registry betrachtet kann hier nun xRegistry zum Einsatz genommen werden. Dabei handelt es sich um ein Projekt, welches dazu dient Metadaten über Ressourcen zu verwalten. Dieses stellt eine REST-basierte Schnittstelle zur Verfügung, um solche Ressourcen zu erstellen, zu bearbeiten, zu löschen und zu erhalten. Alle Informationen die wir vorhin gesehen haben, können in einem grossen Repository abgelegt werden. Solch ein Beispiel gibt es auch auf GitHub.

Hier ein Praxisbeispiel, was man mit dem xRegistry-Tool auch noch machen kann.

Zunächst einmal muss die CLI installiert werden.

1
pip install git+https://github.com/clemensv/cloudevents-registry-cli.git

Dadurch hat man die Möglichkeit, sich Code aus allen Definitionen rauszulesen, die man erstellt hat.

Dabei werden momentan folgende Sprachen unterstützt. Diese können auch mittels xregistry list ausgegeben werden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--languages options:
styles: 
├── py: Python 3.9+
│   └── producer: 
├── asaql: Azure Stream Analytics
│   ├── dispatch: Azure Stream Analytics: Dispatch to outputs by CloudEvent type
│   └── dispatchpayload: Azure Stream Analytics: Dispatch to outputs by CloudEvent type
├── ts: JavaScript/TypeScript
│   └── producerhttp: JavaScript/TypeScript HTTP Producer
├── asyncapi: Async API 2.0
│   └── producer: Async API 2.0 Producer/Publisher
├── openapi: Open API 3.0
│   ├── producer: Open API 3.0 Producer
│   └── subscriber: Open API 3.0 Subscriber
├── java: Java 13+
│   ├── producer: Java CloudEvents SDK endpoint producer class
│   └── consumer: Java CloudEvents SDK endpoint consumer class
└── cs: C# / .NET 6.0+
    ├── azfunctionhttp: C# Azure Function with HTTP trigger
    ├── azfunctioneventgrid: C# Azure Function with Azure Event Grid trigger
    ├── azfunctioneventhubs: C# Azure Function with Azure Event Hubs trigger
    ├── azfunctionservicebus: C# Azure Function with Azure Service Bus trigger
    ├── producer: C# CloudEvents SDK endpoint producer class
    └── consumer: C# CloudEvents SDK endpoint consumer class

Dabei werden folgende Options verwendet:

  • style –> Hiermit kann festgelegt werden, was für Typ erstellt werden soll. Dies verfügabre Auwahl bekommt man über xregistry list
  • language –> Darüber wird definiert in welcher Sprache der Code erstellt werden soll. Auch die Verfügbaren Optionen lassen sich mittels xregistry list erkennen.
  • output
  • projectname
  • definition

Beispiel - Java

1
xregistry generate --style producer --language java --output tmp/testJava --projectname crm --definition samples/message-definitions/contoso-crm.cereg

Dadurch werden folgende Files erstellt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
.
└── testJava
    ├── main
    │   ├── contoso
    │   │   └── crm
    │   │       └── events
    │   │           ├── EventsEventProducer.java
    │   │           ├── ExceptionMessages.java
    │   │           └── RegexPatterns.java
    │   └── crm
    │       ├── CustomerAddressUpdatedEventData.java
    │       ├── CustomerContactAddedEventData.java
    │       ├── CustomerContactUpdatedEventData.java
    │       ├── CustomerCreatedEventData.java
    │       ├── CustomerDeletedEventData.java
    │       ├── CustomerNoteAddedEventData.java
    │       ├── CustomerNoteDeletedEventData.java
    │       ├── CustomerNoteUpdatedEventData.java
    │       ├── CustomerStatusUpdatedEventData.java
    │       └── CustomerUpdatedEventData.java
    └── pom.xml

Beispiel - OpenAPI

1
xregistry generate --style producer --language openapi --output tmp/testOpenApi --projectname crm --definition samples/message-definitions/contoso-crm.cereg

Hier werden folgende definition erstellt:

1
2
└── testOpenApi
    └── Crm.yml

Fazit

Es lässt sich feststellen, dass CloudEvents zunehmend an Bedeutung in der Cloud-Landschaft gewinnt, indem es das Ziel verfolgt, einen einheitlichen Standard für die Übertragung von Events zu etablieren. Das zentrale Problem besteht darin, dass Produzenten und Cloud-Anbieter verschiedene Formate verwenden, was die Interoperabilität über verschiedene Plattformen beeinträchtigt. CloudEvents versucht dieses Dilemma durch die Bereitstellung einer Spezifikation, die die Kommunikation zwischen unterschiedlichen Diensten, Plattformen und Systemen erleichtert, zu lösen. Zahlreiche Integrationen auf namhaften Plattformen wie Google Cloud oder Azure unterstreichen bereits den Erfolg dieser Initiative. Die Verwendung von CloudEvents ermöglicht die Nutzung verschiedener Protokolle und Formate, ohne die Kompatibilität zu gefährden.

Wir bei b-nova unterstützen solche Initiativen voll und ganz und freuen uns darauf, Sie bei Ihrem Projekt zu begleiten! 🔥

Ricky Elfner

Ricky Elfner – Denker, Überlebenskünstler, Gadget-Sammler. Dabei ist er immer auf der Suche nach neuen Innovationen, sowie Tech News, um immer über aktuelle Themen schreiben zu können.