gRPC – entfernte Prozeduren à la Google
gRPC-Services und Messages
In gRPC werden die Schnittstellen in Services spezifiziert. Ein Service stellt eine oder mehrere Methoden bereit und definiert die Messages, die mit dieser Methode ausgetauscht werden. Das ist vergleichbar mit den Parametern und dem Rückgabewert einer Funktion bei der klassischen Programierung oder dem Request/Response-Modell, das viele aus dem REST-Umfeld kennen. Hier mal ein Beispiel eines Services, das sich ein bisschen an unserem Kühlschrank aus dem Event Sourcing Artikel orientiert:
service FridgeService {
rpc Fill (FillRequest) returns (FilledResponse);
rpc FridgeContent (FridgeContentRequest) returns (FridgeContentResponse);
}
Für den "FridgeService" werden zwei Methoden definiert. Mit diesem Service können wir also den Kühlschrank befüllen und den Inhalt des Kühlschranks abfragen. Fehlen noch die Definitionen für die Nachrichten, die unser Service verwendet (ich beschränke mich hier auf den Call "FridgeContent"):
message FridgeContentRequest {
string filterString = 1;
}
message FridgeContentResponse {
message Product {
string name = 1;
int32 count = 2;
string unit = 3;
}
repeated Product content = 1;
Date last_update = 2;
}
Mit dem "FridgeContentRequest" bieten wir dem Anwender des Services die Möglichkeit, die Produkte nach Name zu filtern. Das ist nicht wirklich ausgereift, genügt aber für unser Beispiel.
In der Response definieren wir eine Liste (repeated) von Produkten, die sich derzeit im Kühlschrank befinden. Zusätzlich erstellen wir ein anderes Feld, welches das Datum der letzten Änderung enthält. Und fertig ist das Ganze. :-) Nun noch mehr zu dem, was hinter gRPC und vor allem Protocol Buffers steht.
Protocol Buffers und Event Sourcing
Die zur Übertragung verwendeten Nachrichten werden als Protocol Buffer Messages (Protobuf) definiert. Protobuf Messages werden für die Übertragung in binäre Daten übersetzt. Der Field-Index sind die Zahlen, die den Feldnamen zugewiesen werden. Anhand derer kann das Binärformat aufgebaut und beim Empfänger wieder aufgelöst werden. Und da die Feldnamen selbst nicht übertragen werden, kann die übertragene Datenmenge stark reduziert werden.
gRPC und Protobuf-Messages eignen sich optimal für Event Sourcing. Denn die Commands, mit denen Events erzeugt werden, lassen sich genauso gut als Service-Methoden umsetzen wie Anfragen an das Read Model. Zudem können die entstandenen Events im Protobuf-Format sehr platzsparend abgelegt werden, sodass mehrere millionen Events kein Problem sein sollten. :-)
Die großen Vorteile
Erweiterbarkeit
Die definierten Protobuf-Messages können in vielen Fällen serverseitig erweitert werden, ohne die Kompatibilität zu bestehenden Clients zu verlieren. Neue Protobuf-Felder, die nicht gesetzt werden, erhalten je nach Datentyp einen Standardwert. So können Funktionen zur API hinzugefügt werden – meistens sogar ohne dass eine neue Version der Schnittstelle angelegt werden muss. Und da lediglich der Field-Index der relevante Wert ist, können die Felder umbenannt werden, ohne an Kompatibilität zu verlieren.
Geringer Overhead
Da die Protobuf-Messages direkt über TCP und als Binary übertragen werden, ist der Overhead eines gRPC-Calls wesentlich gerniger als beispielsweise eines REST-Calls über HTTP. Das Binärformat der Nachrichten enthält keine Feldnamen und ist damit wesentlich reduzierter. Bei einer einzelnen Nachricht macht das nicht viel aus. Für ein Unternehmen wie Google, das 10 Milliarden (ja, 10.000.000.000) RPCs pro Sekunde verarbeitet, ist es aber ein durchaus relevanter Faktor. ;-) Und auch bei einer kleineren Größenordnung kann es sich lohnen, den Netzwerkverkehr zu reduzieren, um so eine schnellere Verarbeitung zu ermöglichen.
Sprachenunabhängigkeit
Für gRPC und Protocol Buffers gibt es Bibliotheken in den gängigsten Sprachen – von Java, PHP, Node über Go und Python bis hin zu Kotlin und Runy ist alles dabei. Das ermöglicht in größeren Unternehmen, dass jedes Team die (Micro)Services, für die es zuständig ist, in der prefärierten Sprache entwickelt. Trotzdem können so einheitliche Schnittstellen zwischen den Services verwendet werden.
Fazit
Eine gRPC-API ist eine interessante und vor allem schnelle Alternative oder Ergänzung zu einer REST-API. Durch die Definition der Services und Messages ist das API-Interface einfach zu verstehen und bleibt erweiterbar. Zusätzlich bietet gRPC noch weitere Vorteile wie beispielsweise die Möglichkeit für Streaming RPCs, bei denen die Nachrichten ein- oder sogar beidseitig gestreamt werden können und das Handling so noch mal optimiert werden kann. Dazu eventuell in einem anderen Beitrag mehr.
Nun möchte ich gerne von euch lesen: Habt ihr Erfahrungen mit gRPC?