gRPC – Wegbereiter für die Client-Server-Kommunikation der Zukunft

Die Netzwerktechnik schreitet nach wie vor rasant voran. Um den steigenden Anforderungen in verteilten Computersystemen gerecht zu werden, wurde für Remote Procedure Calls ein neues System namens gRPC entwickelt. Das „g“ steht dabei für Google, die maßgeblich an der Entwicklung beteiligt waren. Wir erklären, was gRPC ist, wie es funktioniert und wo es verwendet wird.

Was ist gRPC?

gRPC ist ein modernes Remote-Procedure-Call-System, das mit neuartigen Verfahrenstechniken die Kommunikation in verteilten Client-Server-Architekturen besonders effizient abwickelt. Dabei setzt es – wie der Vorläufer RPC – auf Prozessebene an. Charakteristisch für die Interprozesskommunikation über gRPC ist das Transparenzprinzip: Die Zusammenarbeit (teils weit) entfernter Instanzen ist so eng und reibungslos, dass kein Unterschied zu einer lokalen Kommunikation zwischen maschineninternen Prozessen spürbar wird.

gRPC wurde 2015 zunächst von Google entwickelt. Heute ist die Cloud Native Computing Foundation (siehe auch: Was ist Cloud Native?) federführend bei der Verbreitung und Weiterentwicklung der Kommunikationstechnik. gRPC ist Open Source, d. h. der Quelltext ist öffentlich zugänglich, Änderungen und Weiterentwicklungen des Codes durch Dritte sind erwünscht und erlaubt.

Den Transport von Datenströmen zwischen entfernten Computern wickelt gRPC standardmäßig mit HTTP/2 ab, für die Strukturierung und Verarbeitung der Daten sind die von Google entwickelten Protocol Buffers zuständig. Letztere werden in Form von einfachen Textdateien mit der Endung .proto gespeichert.

gRPC wird häufig als Framework bezeichnet. Zu den Besonderheiten eines Frameworks zählt, dass es Entwicklern einen Programmierrahmen bereitstellt und dadurch Zeit und Arbeit spart. So enthält das standardisierte Gerüst von gRPC bereits verschiedene Funktionen und Elemente, die nicht immer wieder neu programmiert werden müssen. Das gRPC-Framework definiert zudem genormte Schnittstellen zu bestimmten Quellen (z. B. Datenbanken).

So funktioniert gRPC: Vielsprachig und effizient durch Protocol Buffers und HTTP/2

Protocol Buffers (Protobuf) erfüllen im gRPC-System mehrere Funktionen: Sie dienen als Interface Definition Language (Schnittstellenbeschreibungssprache, kurz: IDL) und beschreiben eine Schnittstelle auf sprachunabhängige Weise. Sie sind also nicht an eine spezielle Programmiersprache (z. B. Java oder C) gebunden. Außerdem definieren sie die zu verwendenden Services und bereitgestellte Funktionen. Für jede Funktion kann angegeben werden, welche Parameter mit einer Anfrage geschickt werden und was als Rückgabewert erwartet werden kann.

Aus der Remote-Perspektive dienen Protocol Buffers als das zugrundeliegende Nachrichtenaustauschformat, das die Nachrichtenstrukturen, -typen und -objekte bestimmt. Sie sorgen dafür, dass Client und Server sich „verstehen“ und auch über große Entfernungen hinweg als funktionale und möglichst effiziente Einheit operieren.

Der Ablauf eines gRPC-Calls sieht bei einer Datenbankabfrage (z. B. „Suche nach Artikelvorrat im Lager“) folgendermaßen aus:

  • Bevor die Suche überhaupt abgewickelt werden kann, braucht es Vorbereitungen. Serverseitig werden auf Basis der Protocol Buffers zunächst ein Service sowie ein gRPC-Server implementiert. Der anfragende Client generiert seinerseits einen dazu passenden Stub. Steht dieser zur Verfügung, ruft die Client-Anwendung die entsprechende Funktion („Suchanfrage nach Artikelbestand“) im Stub auf.
  • Anschließend wird die Anfrage über das Netzwerk an den Server geschickt. Nach deren Empfang mithilfe einer geeigneten Service-Schnittstelle startet der gRPC-Server die eigentliche Produktsuche in der Datenbank.
  • Danach sendet der Server die Antwort an den Client Stub, der den Rückgabewert an die ursprüngliche Anfrageinstanz weiterleitet (z. B. „Zahl der gefundenen Artikel“).

Client- und serverseitige Anwendungen können in unterschiedlichen Programmiersprachen geschrieben werden. gRPC überwindet diese Grenzen durch spezielle Schnittstellen und Übersetzungsmechanismen.

Für den intermaschinellen Hin- und Rücktransport der Datenströme (Proto Request und Proto Response) wird HTTP/2 in spezielle Netzwerkprotokolle wie TCP/IP oder UDP/IP eingebettet. Die Streams transferieren kompakte Binärdaten, die bei der für Remote Procedure Calls typischen Serialisierung (Marshalling) entstehen. Um die vollkommen abstrakten Datenstrukturen client- und serverseitig in weiteren Schritten verarbeiten zu können, wird das Übermittelte auch wieder deserialisiert (Unmarshalling).

gRPC-Workflow und erste Schritte via Protocol Buffers

Der typische gRPC-Workflow gliedert sich in vier Schritte:

  1. Definition des Servicevertrags für die Interprozesskommunikation: Die aufzusetzenden Services sowie grundlegende Parameter und Rückgabetypen, die per Remote aufgerufen werden können, werden bestimmt.
  2. Erzeugung des gRPC-Codes aus der .proto-Datei: Spezielle Compiler (Kommandozeilenwerkzeuge mit dem Namen „protoc“) generieren aus gespeicherten .proto-Dateien den operativen Code mit den entsprechenden Klassen für eine gewünschte Zielsprache (z. B. C++, Java).
  3. Implementierung des Servers in der gewählten Sprache.
  4. Erstellung des Client Stubs, der den Service aufruft; anschließend wird bzw. werden die Anfrage(n) über Server und Client(s) abgewickelt.

Bei einer Datenbankabfrage, die nach einem Produkt in einem Lagerbestand (inventory) sucht, sehen die ersten konkreten Schritte in der aktuellen Protocol-Buffers-Syntax (Version: proto3) wie folgt aus:

syntax = "proto3";
package grpc_service;
import "google/protobuf/wrappers.proto";
service InventoryService {
	rpc getItemByName(google.protobuf.StringValue) returns (Items);
	rpc getItemByID(google.protobuf.StringValue) returns (Item);
	 rpc addItem(Item) returns (google.protobuf.BoolValue);
}
 
message Items {
  string itemDesc = 1;
  repeated Item items = 2;
}
 
message Item {
	string id = 1;
	string name = 2;
	string description = 3;
}

In dem Beispiel verwendet die Datenbankabfrage spezielle „Wrapper-Bibliotheken“ des gRPC-Frameworks, die relevante Übersetzungsprozeduren bereits vorprogrammiert zur Verfügung stellen und zu Beginn importiert werden. Sie sorgen in vielsprachigen und disparaten Client-Server-Architekturen dafür, dass eigentlich inkompatible Schnittstellen miteinander kommunizieren können. So werden etwa die zum Lesen und Schreiben von Nachrichten erforderlichen Klassen generiert.

Wie die Servicedefinition (inventory.proto) die Abfrage einer Datenbank in einer Client-Server-Architektur regelt, zeigt folgendes Schaubild:

HTTP/2: Leistungsoptimiertes Streaming

HTTP/2 spielt bei gRPC eine zentrale Rolle, da es den Transfer kompakter Binärdaten ermöglicht und den Austausch von Nachrichten und Daten besonders effizient gestaltet. Das Netzwerkprotokoll stellt vier Varianten für Remote Procedure Calls zur Verfügung:

  1. Unäre RPCs sind das einfachste gRPC-Muster. Dabei sendet der Client eine einzelne Anforderung an den Server. Wie bei einem normalen Funktionsaufruf erhält er dann eine einzelne Antwort zurück.

Beispiel: rpc SayHello (HelloRequest) gibt zurück (HelloResponse)

  1. Bei Server-Streaming-RPCs ist ein komplexerer Nachrichtenaustausch innerhalb eines einzelnen RPC-Aufrufs möglich. Zunächst sendet der Client eine Anforderung an den Server. Dann erhält er als Rückantwort vom Server einen Stream mit einer umfangreicheren Nachrichtenfolge (effiziente Nachrichtenbestellung innerhalb eines einzelnen RPC-Aufrufs). Der Client liest diesen Stream dann aus, bis keine Nachrichten mehr vorhanden sind.

Beispiel: rpc LotsOfReplies (HelloRequest) gibt zurück (stream HelloResponse)

  1. Client-Streaming-RPC kehrt den Prozess um: Der Client schreibt eine Folge von Nachrichten und sendet diese dann via Stream an den Server. Nachdem der Client die Nachrichten verfasst hat, wartet er darauf, dass der Server sie liest und die Antwort zurückgibt. Auch hier erfolgt die Nachrichtenbestellung innerhalb eines einzelnen RPC-Aufrufs.

Beispiel: rpc LotsOfGreetings (stream HelloRequest) gibt zurück (HelloResponse)

  1. Bidirektionale Streaming-RPCs sind die komplexeste Kommunikationsform, bei der beide Seiten eine Folge von Nachrichten senden. Beide Daten-Streams arbeiten unabhängig voneinander, so dass Client und Server in beliebiger Reihenfolge lesen und schreiben können: So kann der Server warten, bis alle Client-Nachrichten eingegangen sind, bevor er seine Antworten schreibt. Er kann aber auch abwechselnd eine Nachricht lesen und dann eine Nachricht schreiben. Möglich ist zudem eine andere Kombination von Lese- und Schreibvorgängen.

Beispiel: rpc BidiHello (stream HelloRequest) gibt zurück (stream HelloResponse)

Die Varianten 2 bis 4 etablieren mit verschachtelten Requests ein besonders effizientes Multiplexing, bei dem innerhalb einer einzelnen TCP-Verbindung mehrere Signale gebündelt und simultan über das Netzwerk übertragen werden können. Blockierungen im Datenverkehr werden durch das leistungsfähige HTTP/2-Protokoll überwunden.

Die Vor- und Nachteile von gRPC

gRPC hat viele Vorteile: Die Technologie lässt sich relativ leicht umsetzen, weil sie bei der Erstellung der .proto-Dateien eine einfache und recht schnell erlernbare IDL verwendet. Damit können selbst betagte Programme unkompliziert um eine leistungsfähige gRPC-Schnittstelle erweitert werden und deutlich schneller auch große Dateien übertragen.

Zudem ist gRPC vielfach getestet und hochskalierbar, wodurch auch komplexere und umfangreichere Kommunikationen z. B. in global vernetzten Client-Server-Architekturen als Einsatzgebiet infrage kommen. Dabei erhöht HTTP/2 die Effizienz nicht nur durch Multiplexing und bidirektionales Streaming. Es sind auch Header-Komprimierungen möglich, die das Datenvolumen von Anforderungen und Antworten im Netzwerk nennenswert reduzieren.

Durch den mehrschichtigen und stark standardisierten Aufbau des gRPC-Frameworks lässt sich der Programmieraufwand reduzieren. Entwickler können sich somit primär auf die Implementierung der Methoden konzentrieren. Sind Anpassungen nötig, profitieren Programmierer und Systementwickler von der freien Zugänglichkeit der Quellcodes.

Protocol Buffers und die entsprechenden Protobuf Compiler ermöglichen zudem eine grenzüberscheitende Kommunikation: Unterschiedliche Betriebssysteme, disparate Komponenten von Client-Server-Architekturen und verschiedene Programmiersprachen stellen keine Hürde mehr dar. So kann eine Software, die in C geschrieben ist, etwa mit Java-Software kommunizieren. Protobuf Compiler stehen mittlerweile für viele weitere Sprachen zur Verfügung, z. B. für C#, C++, Go, Objective-C, Java, Python, Node.js, Android Java, Swift, Ruby und PHP.

Vorteilhaft ist auch die Flexibilität von gRPC. Es kann beispielsweise gleichermaßen zum Datenaustausch von Microservices oder von mobilen Apps verwendet werden, die ihre Daten mit Servern teilen. Ein weiterer Pluspunkt: Das Protokoll erlaubt die Implementierung von aktuellen Sicherheitstechnologien. gRPC verfügt über eine integrierte Authentifizierung und fördert die Verwendung von SSL/TLS zur Authentifizierung und zur Verschlüsselung des Austauschs.

Zu den Schwächen von gRPC zählen: Das Testen von gRPC-Schnittstellen ist beim derzeitigen Stand der Entwicklung noch verbesserungswürdig. gRPC-Nachrichten, die mit protobuf codiert werden, sind nicht von Menschen lesbar. Bei der Analyse des Datenverkehrs und speziell bei der Fehlersuche und -behebung (Debuggen) müssen also zusätzliche Instanzen eingesetzt werden, um den Code in eine verständliche Form zu überführen und dadurch Fehlerquellen zu lokalisieren. Weitere Nachteile resultieren aus der Vernetzung von verteilten Client-Server-Architekturen. gRPC verbindet Rechner über Entfernungen und ist somit anfälliger als lokale Systeme. Es ist von einem stabilen und leistungsfähigen Netz abhängig, zudem sollten Netzwerk, Datenverkehr, Übertragungsprotokolle sowie Client und Server Hackern keine Angriffspunkte bieten. Ein weiterer Nachteil ist, dass gRPC kein Multicasting unterstützt.

gRPC und REST im Vergleich

Aufgrund der positiven Eigenschaften stellt gRPC eine konkurrenzfähige Alternative zu REST (Representational State Transfer) dar. Letzteres eignet sich besonders gut für einfache Services, während gRPC seine Stärken bei komplexeren Schnittstellen (APIs) und Services ausspielt. REST nutzt für den Datenaustausch zwischen Anwendungen in der Regel das Datenformat JSON, das textbasiert operiert und dadurch die Netzwerkressourcen belastet.

gRPC hingegen kann durch Protocol Buffers und HTTP/2 einen deutlich kompakteren Datenstrom organisieren. So wird der Speicherbedarf durch Serialisierung und Binarisierung der Daten im Vergleich etwa zu JSON um nahezu 70 Prozent gesenkt. Zudem sorgt das bidirektionale Streaming, das ohne Blockierungen beim Datenaustausch funktioniert, gegenüber REST für wesentliche Leistungs- und Geschwindigkeitsvorteile.

Derzeit ist die Zusammenarbeit mit Web-Apps verbesserungswürdig, da diese häufig nicht für den Einsatz von Protokollpuffern, den gRPC-typischen „Vertrag-zuerst-Ansatz“ sowie die Contract First APIs des gRPC-Frameworks optimiert sind. Nachteilig für die Zusammenarbeit mit Webapplikationen ist, dass noch kein gRPC-Dienst direkt von einem Browser aus aufgerufen werden kann. Bei REST ist das kein Problem, da das klassische HTTP-Protokoll im Gegensatz zum neueren HTTP/2 von allen Browsern unterstützt wird. Allerdings lässt sich das Manko mit vertretbarem Aufwand umgehen, sodass derselbe Dienst für eine Webapplikation und eine mobile App eingesetzt werden kann. Eine Option in diesem Bereich ist gRPC-Web. gRPC-Entwickler arbeiten noch an weiteren Lösungen, die die Zusammenarbeit von gRPC und webbasierten Tools möglichst einfach gestalten sollen.

Wo wird gRPC verwendet?

gRPC eignet sich besonders für eine effiziente Interprozesskommunikation in verteilten Client-Server-Architekturen, die Wert auf niedrige Latenz und einen hohen Daten- und Nachrichtendurchsatz legt. In und zwischen voneinander entfernten Rechenzentren wird gRPC häufig eingesetzt, um Dienste oder Microservices miteinander zu verbinden. Da gRPC-Tools die meisten gängigen Entwicklungssprachen unterstützen, werden sie häufig in mehrsprachigen Umgebungen verwendet.

Schnelligkeit, Effizienz und Vielsprachigkeit begünstigen den Einsatz von gRPC im mobilen Bereich und bei der Kommunikation von Apps. gRPC regelt vermehrt die letzte Meile verteilter Datenverarbeitung, indem es Geräte, mobile Anwendungen und Browser mit Backend-Diensten verbindet.

Das leistungsfähige Streaming via HTTP/2 prädestiniert gRPC zudem für die Punkt-zu-Punkt-Echtzeitkommunikation. Das Internet of Things (Smart-Home-Technologien) profitiert von dem ressourcenschonenden Verfahren, da es vermehrt die Kommunikation von Low Resource Clients regelt. Aufgrund der Leistungsvorteile und der einfachen Entwicklung könnte die Kommunikationstechnik in Zukunft in der Cloud eine führende Rolle spielen und damit die derzeitige Dominanz von REST relativieren. gRPC wird momentan ebenfalls als Alternative zu XML (Extensible Markup Language) gehandelt.

Hinweis

XML ist ein häufig verwendetes Format zum Datenaustausch und zur strukturierten Speicherung von Informationen.