In der heutigen Text möchte ich genauer auf gRPC und REST eingehen, wahrscheinlich zwei der am häufigsten verwendeten Ansätze zur Erstellung von APIs heutzutage.
I will start with a short characteristic of both tools — what they are and what they can offer. Then I will compare them according to seven categories, in my opinion, most crucial for modern-day systems.
Die Kategorien sind wie folgt:
- Unterliegende HTTP-Protokolle
- Unterstützte Datenformate
- Datengröße
- Durchsatz
- Definitionen
- Einfachheit der Umsetzung
- Tooling-Unterstützung
Der Warum
Wenn Menschen „API“ hören, denken sie wahrscheinlich sofort an REST-API. Allerdings ist REST nur einer von vielen Ansätzen zum Aufbau von APIs. Es ist keine Allheilmittel-Lösung für alle Anwendungsfälle. Es gibt andere Möglichkeiten, wobei RPC (Remote Procedure Call) nur einer von ihnen ist und gRPC wahrscheinlich das erfolgreichste Framework für die Arbeit mit RPC ist.
Trotz der recht hohen Reife und Effizienz der Technologie gilt gRPC immer noch als neu. Daher ist es weniger weit verbreitet als REST, obwohl es in einigen Anwendungsfällen recht praktisch ist.
Mein Hauptgrund für diesen Blog-Beitrag ist es, gRPC bekannt zu machen und Anwendungsfälle aufzuzeigen, in denen es hervorstechen kann.
Was ist REST?
REST, oder Representational State Transfer, ist wahrscheinlich die gebräuchlichste Methode zur Erstellung einer Anwendung, die eine beliebige Art von API offenbart. Es nutzt HTTP als Basiskommunikationsmedium. Aufgrund dessen kann es alle Vorteile von HTTP nutzen, wie z.B. das Zwischenspeichern.
Darüber hinaus, da es von Anfang an zustandslos ist, ermöglicht REST eine einfache Trennung zwischen Client und Server. Der Client muss nur die vom Server bereitgestellte Schnittstelle kennen, um effektiv mit ihm zu kommunizieren und hängt in keiner Weise von der Serverimplementierung ab. Die Kommunikation zwischen Client und Server basiert auf einer Anforderungs- und Antwortbasis, wobei jede Anforderung eine klassische HTTP-Anforderung ist.
REST ist weder ein Protokoll noch ein Werkzeug (in gewissem Umfang): Es ist ein architektonischer Ansatz zur Erstellung von Anwendungen. Die Dienste, die dem REST-Ansatz folgen, werden als RESTFul-Dienste bezeichnet. Als Architektur legt es mehrere Einschränkungen für seine Benutzer auf. Insbesondere:
- Client-Server-Kommunikation
- Zustandslose Kommunikation
- Zwischenspeichern
- Einheitliche Schnittstelle
- Geländertes System
- Code on demand
Die zwei entscheidenden Konzepte von REST sind:
- Endpunkte: Eine eindeutige URL (Uniform Resource Locator), die ein bestimmtes Resource repräsentiert; kann als Weg betrachtet werden, um eine bestimmte Operation oder Datenelement über das Internet zugänglich zu machen
- Resource: Ein bestimmtes Datenelement, das unter einer spezifischen URL verfügbar ist.
Darüber hinaus gibt es eine Beschreibung namens Richardson-Reifungsmodell — ein Modell, das den Grad der „Professionalität“ in REST-APIs beschreibt. Es unterteilt REST-APIs in 3 Stufen (oder 4, je nachdem, ob man Stufe 0 mitzählt), basierend auf der Menge an Merkmalen, die eine bestimmte API aufweist.
Ein solches Merkmal ist, dass der REST-Endpunkt Substantive in der URL verwenden und korrekte HTTP-Anforderungsmethoden verwenden sollte, um seine Ressourcen zu verwalten.
- Beispiel: DELETE user/1 statt GET user/deleteById/1
Für HTTP-Methoden und ihre zugehörigen Aktionen sieht es wie folgt aus:
- GET — Eine bestimmte Ressource oder eine Sammlung von Ressourcen abrufen
- POST — Eine neue Ressource erstellen
- PUT — Ganze Ressource upserten
- PATCH — Teilweise Aktualisierung einer bestimmten Ressource
- DELETE — Eine bestimmte Ressource anhand der ID entfernen
Das Reifungsmodell legt noch viel mehr fest; zum Beispiel ein Konzept namens HyperMedia. HyperMedia verbindet die Darstellung von Daten und die Steuerung von Aktionen, die Clients ausführen können.
A full description of the maturity model is out of the scope of this blog — you can read more about it here.
Hinweis: Viele der hier erwähnten Dinge sind subtiler als hier beschrieben. REST ist ein ziemlich großes Thema und würde eine ganze Reihe von Artikeln wert sein. Trotzdem ist alles hier im Einklang mit allen allgemein bekannten besten REST-Praktiken.
Was ist gRPC?
Es handelt sich um eine weitere Implementierung des relativ alten Konzepts des Remote Procedure Call. Es wurde von Leuten von Google entwickelt – deshalb befindet sich ein „g“ in seinem Namen. Es ist wahrscheinlich das modernste und effizienteste Werkzeug für die Arbeit mit RPCs und zudem ein CNCF-Inkubations Projekt.
gRPC verwendet Googles Protocol Buffers als Serialisierungsformat und nutzt HTTP/2 als Transportmedium für Daten, obwohl gRPC auch mit JSON als Datenschicht arbeiten kann.
Die grundlegenden Bausteine von gRPC umfassen:
- Methode: Der grundlegende Baustein von gRPC, jede Methode ist ein Remote-Prozeduraufruf, der einige Eingaben nimmt und eine Ausgabe zurückgibt. Sie führt eine einzelne Operation aus, die weiter in der bevorzugten Programmiersprache implementiert ist. Stand jetzt unterstützt gRPC 4 Arten von Methoden:
- Unär: Klassisches Anfrage-Antwort-Modell, bei dem die Methode Eingabe nimmt und Ausgabe zurückgibt
- Server-Streaming: Methoden nehmen eine Nachricht als Eingabe entgegen und geben einen Nachrichtenstrom als Ausgabe zurück. gRPC garantiert die Nachrichtenreihenfolge innerhalb eines einzelnen RPC-Aufrufs.
- Client-Streaming: Die Methode nimmt einen Strom von Nachrichten als Eingabe, verarbeitet sie, bis keine Nachrichten mehr übrig sind, und gibt dann eine einzelne Nachricht als Ausgabe zurück. Ähnlich wie oben garantiert gRPC die Nachrichtenreihenfolge innerhalb eines einzelnen RPC-Aufrufs.
- Bidirektionale Streaming: Die Methode nimmt den Stream als Eingabe und gibt den Stream als Ausgabe zurück, wobei effektiv zwei lesende und schreibende Streams verwendet werden. Beide Streams arbeiten unabhängig voneinander und die Nachrichtenreihenfolge wird auf Streamebene beibehalten.
- Dienst: Steht für eine Gruppe von Methoden – jede Methode muss innerhalb des Dienstes einen eindeutigen Namen haben. Dienste beschreiben auch Funktionen wie Sicherheit, Zeitüberschreitungen oder Wiederholungen.
- Nachricht: Ein Objekt, das die Eingabe oder Ausgabe von Methoden darstellt.
Die gRPC-API-Definitionen sind in Form von .proto-Dateien geschrieben, die alle drei oben genannten grundlegenden Bausteine enthalten. Darüber hinaus stellt gRPC einen Protokollbuffer-Compiler bereit, der Client- und Dienstcode aus unseren .proto-Dateien generiert.
Wir können Server-seitige Methoden auf die gewünschte Weise implementieren. Wir müssen uns jedoch an den Eingabe-Ausgabe-Vertrag der API halten.
Auf der Client-Seite gibt es ein Objekt namens Client (oder Stub) – ähnlich wie ein HTTP-Client. Er kennt alle Methoden des Servers und kümmert sich einfach um das Aufrufen von Remote-Prozeduren und das Zurückgeben ihrer Antworten.
Der Vergleich
Unterliegendes HTTP-Protokoll
Dies ist die erste Kategorie und wahrscheinlich die wichtigste, da ihr Einfluss auch in anderen sichtbar sein kann.
Im Allgemeinen basiert REST auf Anfrage-Antwort und verwendet HTTP/1.1 als Transportmedium. Wir müssen ein anderes Protokoll wie WebSocket (mehr dazu hier) oder jede Art von Streaming oder länger andauernder Verbindung verwenden.
Wir können auch einen hackigen Code umsetzen, um REST wie Streaming aussehen zu lassen. Darüber hinaus erfordert HTTP/1.1 REST eine Verbindung pro Anfrage-Antwort-Austausch. Ein solcher Ansatz kann für lange laufende Anfragen oder bei eingeschränkten Netzwerkkapazitäten problematisch sein.
Natürlich können wir HTTP/2 für den Aufbau von REST-ähnlichen APIs verwenden; allerdings unterstützen nicht alle Server und Bibliotheken HTTP/2 noch. Daher können Probleme an anderen Stellen auftreten.
gRPC hingegen verwendet ausschließlich HTTP/2. Es ermöglicht das Senden mehrerer Anfrage-Antwort-Paare über eine einzige TCP-Verbindung. Ein solcher Ansatz kann für unsere Anwendung einen erheblichen Leistungsschub darstellen.
- Ergebnis: Leichte Überlegenheit von gRPC
Unterstützte Datenformate
Angenommen der Standardfall, wenn eine REST-API HTTP/1.1 verwendet, dann kann sie viele Formate unterstützen.
REST legt grundsätzlich keine Einschränkungen bezüglich Nachrichtenformat und -stil fest. Im Wesentlichen ist jedes Format, das in einfachen alten Text serialisiert werden kann, gültig. Wir können jedes Format verwenden, das für einen bestimmten Szenario am besten geeignet ist.
Das beliebteste Format für den Datenaustausch in REST-Anwendungen ist definitiv JSON. XML kommt zweitbeliebtesten, vor allem wegen der großen Anzahl älterer/legister Anwendungen.
Wenn man jedoch REST mit HTTP/2 verwendet, dann werden nur binäre Austauschformate unterstützt. In diesem Fall können wir Protobuf oder Avro verwenden. Natürlich kann ein solcher Ansatz Nachteile haben, aber dazu später mehr.
In der Zwischenzeit unterstützt gRPC nur zwei Formate für den Datenaustausch:
- Protobuf – Standardmäßig
- JSON — Wenn Sie eine Integration mit einer älteren API
vornehmen müssen, wenn Sie sich für JSON entscheiden, verwendet gRPC JSON als Kodierungsformat für Nachrichten und GSON als Nachrichtenformat. Darüber hinaus erfordert die Verwendung von JSON einige zusätzliche Konfigurationen. Hier ist die gRPC Dokumentation dazu.
- Ergebnis: Sieg für REST, da es mehr Formate unterstützt.
Datengröße
Standardmäßig verwendet gRPC ein binäres Datenaustauschformat, das die Größe der über das Netz gesendeten Nachrichten ERHEBLICH reduziert: Forschung zeigt, dass es um 40–50% weniger Bytes beträgt — meine Erfahrung aus einem früheren Projekt zeigt sogar 50–70% weniger.
Der obige Artikel bietet einen relativ tiefgreifenden Größenvergleich zwischen JSON und Protobuff. Der Autor stellte auch ein Tool zur Verfügung, um JSONs und Binärdateien zu generieren. So können Sie seine Experimente wiederholen und die Ergebnisse vergleichen.
Die Objekte aus dem Artikel sind ziemlich einfach. Dennoch gilt die allgemeine Regel — je mehr eingebettete Objekte und je komplexer die Struktur von JSON, desto größer wird es im Vergleich zu Protobuf sein. Eine Größendifferenz von 50% zugunsten von Protobuf ist ein guter Ausgangspunkt.
Die Differenz kann minimiert oder beseitigt werden, indem das binäre Austauschformat für REST verwendet wird. Dennoch ist es weder der gebräuchlichste noch der am besten unterstützte Weg, RESTful APIs zu implementieren, sodass andere Probleme auftreten können.
- Ergebnis: Im Standardfall, Sieg für gRPC; im Fall beider Verwendung von binären Datenformaten, ein Unentschieden.
Durchsatz
Wiederum hängt beim REST alles vom zugrunde liegenden HTTP-Protokoll und dem Server ab.
Im Standardfall, REST basierend auf HTTP/1.1, kann selbst der leistungsfähigste Server die Leistung von gRPC nicht übertreffen, insbesondere wenn wir die Seriellisierungs- und Deserialisierungsoverhead bei der Verwendung von JSON hinzufügen. Obwohl sich der Unterschied beim Wechsel zu HTTP/2 verringert.
Was das maximale Durchsatz angeht, ist in beiden Fällen HTTP ein Transportmedium und hat daher das Potenzial, sich ins Unendliche zu skalieren. Somit hängt alles von den verwendeten Tools und dem genauen Vorgehen mit unserer Anwendung ab, da es durch das Design keine Grenzen gibt.
- Ergebnis: Im Standardfall, gRPC; im Fall beider Verwendung von binären Daten und HTTP/2, Unentschieden oder leichter Sieg für gRPC.
Definitionen
In diesem Teil werde ich beschreiben, wie wir unsere Nachrichten und Dienste in beiden Ansätzen definieren.
In den meisten REST-Anwendungen erklären wir einfach unsere Anfragen und Antworten als Klassen, Objekte oder in welcher Struktur auch immer eine bestimmte Sprache unterstützt. Dann vertrauen wir auf vorgegebene Bibliotheken zur Serialisierung und Deserialisierung von JSON/XML/YAML oder welchem Format wir auch immer benötigen.
Darüber hinaus gibt es laufende Bemühungen, Werkzeuge zu entwickeln, die in der gewählten Programmiersprache Code generieren können, basierend auf REST-API-Definitionen aus Swagger. Allerdings scheinen diese noch in der Alpha-Version zu sein, sodass es weiterhin einige Fehler und kleinere Probleme geben könnte, die ihre Verwendung erschweren.
Es besteht kaum ein Unterschied zwischen binären und nicht-binären Formaten für REST-Anwendungen, da die Regeln in beiden Fällen mehr oder weniger gleich sind. Bei binären Formaten müssen wir lediglich alles in der von einem bestimmten Format erforderlichen Weise definieren.
Darüber hinaus haben wir unsere REST-Dienste über Methoden oder Annotationen aus unserer zugrunde liegenden Bibliothek oder dem Framework definiert. Das Tool ist ferner dafür zuständig, diese zusammen mit anderen Konfigurationen der Außenwelt zur Verfügung zu stellen.
Im Falle von gRPC haben wir Protobuf als Standard und de facto einzige Methode zum Schreiben von Definitionen. Wir müssen alles deklarieren: Nachrichten, Dienste und Methoden in .proto-Dateien, sodass die Sache ziemlich einfach ist.
Anschließend verwenden wir das von gRPC bereitgestellte Tool, um Code für uns zu generieren, und müssen nur noch unsere Methoden implementieren. Danach sollte alles wie gewünscht funktionieren.
Zudem unterstützt Protobuf das Importieren, sodass wir unsere Einrichtung auf mehrere Dateien verteilen können, was recht einfach ist.
- Ergebnis: Hier gibt es keinen Sieger, nur eine Beschreibung und einen Tipp von mir: Wähle diejenige Herangehensweise, die dir am besten gefällt.
Einfache Implementierung
In diesem Teil werde ich die Bibliotheks-/Frameworksupport für jede Herangehensweise in modernen Programmiersprachen vergleichen.
Im Allgemeinen habe ich in meiner kurzen Karriere als Softwareentwickler bei jeder Programmiersprache (Java, Scala, Python) mindestens 3 größere Bibliotheken/Frameworks für die Erstellung von REST-ähnlichen Anwendungen gefunden, ganz zu schweigen von einer ähnlichen Anzahl von Bibliotheken zur Parsing von JSONs in Objekte/Klassen.
Darüber hinaus, da REST standardmäßig menschenlesbare Formate verwendet, ist es für Neulinge einfacher zu debuggen und zu arbeiten. Dies kann auch Auswirkungen auf den Zeitpunkt der Bereitstellung neuer Funktionen haben und Ihnen dabei helfen, Bugs in Ihrem Code zu bekämpfen.
Kurz gesagt, die Unterstützung für REST-stilige Anwendungen ist zumindest sehr gut.
In Scala gibt es sogar ein Tool namens tapir — für das ich das Vergnügen hatte, für einige Zeit einer der Maintainer zu sein. Tapir erlaubt es uns, unseren HTTP-Server zu abstrahieren und Endpunkte zu schreiben, die für mehrere Server funktionieren.
gRPC selbst bietet eine Client-Bibliothek für über 8 beliebte Programmiersprachen. Dies reicht normalerweise aus, da diese Bibliotheken alles enthalten, was zum Erstellen einer gRPC-API benötigt wird. Darüber hinaus kenne ich Bibliotheken, die für Java (über Spring Boot Starter) und für Scala höhere Abstraktionen bieten.
Ein weiteres Merkmal ist, dass REST heute als weltweiter Standard und Einstiegspunkt für die Erstellung von Diensten angesehen wird, während RPC und insbesondere gRPC trotz ihres etwas betagten Alters nach wie vor als Neuheit betrachtet werden.
- Ergebnis: REST, da es weiter verbreitet ist und umfangreichere Bibliotheken und Frameworks herum hat
Werkzeugunterstützung
Bibliotheken, Frameworks und allgemeine Marktanteile wurden oben behandelt, also möchte ich in diesem Teil die Werkzeuge rund um beide Stile besprechen. Dazu gehören Werkzeuge für Tests, Leistungs-/Belastungstests und Dokumentation.
Automatisierte Tests/Tests
Zunächst gibt es im Fall von REST Werkzeuge zur Erstellung automatisierter Tests, die in verschiedenen Bibliotheken und Frameworks integriert sind oder als separate Werkzeuge mit diesem einzigen Zweck entwickelt wurden, wie REST-assured.
Im Fall von gRPC können wir einen Stub generieren und ihn für Tests verwenden. Wenn wir es noch genauer haben möchten, können wir den generierten Client als separates Anwendungsprogramm verwenden und ihn als Grundlage für unsere Tests auf der echten Dienstebene nutzen.
Was die Unterstützung externer Werkzeuge für gRPC betrifft, kenne ich:
- Postman-App Unterstützung für gRPC
- Der JetBrains HTTP-Client, der in ihren IDEs verwendet wird, kann gRPC auch mit einer gewissen Mindestkonfiguration unterstützen
- Ergebnis eins: Sieg für REST; allerdings scheint sich die Situation für gRPC zu verbessern.
Leistungstests
Hier bietet REST erhebliche Vorteile, da Werkzeuge wie JMeter oder Gatling das Stress-Testing von REST-APIs zu einer ziemlich einfachen Aufgabe machen.
Leider bietet gRPC keine solche Unterstützung. Ich bin mir bewusst, dass die Leute von Gatling den gRPC-Plugin in der aktuellen Gatling-Version integriert haben, sodass die Situation scheinbar besser wird.
Bislang hatten wir jedoch nur einen inoffiziellen Plugin und eine Bibliothek namens ghz. Alle diese sind gut; es ist jedoch nicht die gleiche Unterstützungsebene wie bei REST.
- Ergebnis zwei: Sieg für REST; allerdings scheint sich die Situation für gRPC erneut zu verbessern 😉
Dokumentation
Im Fall der API-Dokumentation ist der Sieg erneut bei REST, mit OpenAPI und Swagger sind im gesamten Industriezweig weit verbreitet und stellen die De-facto-Standard dar. Fast alle Bibliotheken für REST können Swagger-Dokumentation mit geringem Aufwand oder direkt aus dem Kasten heraus veröffentlichen.
Leider hat gRPC nichts Vergleichbares.
Allerdings stellt sich die Frage, ob gRPC überhaupt ein Werkzeug wie dieses benötigt. gRPC ist durch seine Konstruktion deskriptiver als REST, sodass zusätzliche Dokumentationstools möglicherweise.
Im Allgemeinen sind .proto-Dateien mit unserer API-Beschreibung deklarativer und kompakter als der Code, der für die Erstellung unseres REST-API-Codes verantwortlich ist, also möglicherweise benötigt man keine weitere Dokumentation von gRPC. Die Antwort lasse ich Ihnen überlassen.
- Ergebnis drei: Sieg für REST; allerdings bleibt die Frage der gRPC-Dokumentation offen.
Insgesamt Ergebnis:
A significant victory for REST
Zusammenfassung
Die endgültige Punktetabelle sieht folgendermaßen aus.

Die Punkte sind gleichmäßig zwischen beiden Stilen aufgeteilt, mit jeweils drei Siegen und einer Kategorie ohne klaren Gewinner.
Es gibt kein Allheilmittel: Denken Sie nur darüber nach, welche Kategorien für Ihre Anwendung am wichtigsten sein könnten und wählen Sie dann den Ansatz, der in den meisten von ihnen gewonnen hat – zumindest ist dies meine Empfehlung.
Was meine persönliche Präferenz betrifft, würde ich gRPC ausprobieren, wenn ich kann, da es in meinem letzten Projekt ziemlich gut funktioniert hat. Es könnte eine bessere Wahl sein als der gute alte REST-Kumpel.
Wenn Sie jemals Hilfe bei der Wahl zwischen REST und gRPC benötigen oder mit anderen technischen Problemen konfrontiert sind, lassen Sie es mich einfach wissen. Vielleicht kann ich Ihnen helfen.
Vielen Dank für Ihre Zeit.