APIs dienen als Verbindungsstück zwischen Daten und Verarbeitung und erlauben uns damit, Daten im richtigen Kontext als Informationen zu interpretieren. Passende fachliche Themen sind dabei präsenter denn je und erreichen bald auch den Endverbraucher beispielsweise mit dem Digitalen Produktdatenpass, der Kreislaufwirtschaft und Transparenz bei Lieferketten sicherstellen und darüber Auskunft geben soll. Und genau diese Informationen werden von APIs bereitgestellt oder entsprechend verarbeitet. Von technischer Seite sind Standards wie OpenTelemetry nach wie vor Dauerbrenner, ebenso wie der Datenaustausch innerhalb von Systemen. Dafür benötigen wir einen Kommunikationskanal, der von guter Qualität ist, also quasi unsere Erwartungen erfüllt. Diese können funktionale und nicht-funktionale Anforderungen sein, ein strukturierter Inhalt oder die Struktur selbst. SOAP als in die Jahre gekommener Standard ist durch REST abgelöst worden, aber auch die RPC-orientierte Konkurrenz gRPC darf dabei nicht unerwähnt bleiben. Im Rahmen dieses Blogartikels möchte ich daher der Frage auf den Grund gehen, welche der beiden Varianten vielleicht die bessere ist, und dazu etwas genauer hinschauen.
REST, ...
... oder ausgeschrieben „Representational State Transfer“, verwendet den HTTP-1.1-Standard als Basis für die Kommunikation. Die Übertragung erfolgt dabei immer in der Form, dass ein Request abgeschickt und von der Gegenseite mit einer Antwort quittiert wird. Die Übertragung der Daten erfolgt dabei als einfacher Text. Dabei werden die bekannten HTTP-Methoden wie z. B. GET, POST, PUT, DELETE verwendet, um Daten über verschiedene Endpunkte zu verarbeiten. Diese Daten werden von REST als Ressourcen betrachtet, sodass quasi dienstleistungsorientiert mit einer Anfrage angefordert wird: „Hole mir dies!“ (GET) oder „Lösche jenes!“ (DELETE). Je nach Art der Anfrage müssen Daten im HTTP-Body angehangen werden, entweder in JSON oder XML.
Das sorgt dafür, dass REST unabhängig von der Programmiersprache des Sender- und Empfängersystems ist und wir sprachagnostisch arbeiten können. OpenAPI als Interface Definition Language (IDL) ermöglicht uns die Generierung des benötigten Consumer- und Producer-Codes in Form von Stubs. Damit sparen wir Zeit bei der Implementierung und beim Bugfixing, da wir Methoden und Tests direkt gegen die generierten Typen und Schnittstellen entwickeln können und somit nur einen Teil der Implementierung selbst schreiben müssen. Das Gleiche gilt für Updates und den dazugehörigen Boilerplate-Code. Darüber hinaus ist es sinnvoll, Endpunkte und erwartete Response-Codes beispielsweise via Contract-Testing zu dokumentieren. Um unsere REST-API änderbar zu gestalten, empfiehlt es sich außerdem, über ein Konzept zur Endpunkt-Versionierung in URL, Body oder HTTP-Header nachzudenken. Die Kommunikation über REST versteht sich außerdem als zustandslos. Das bedeutet, dass alle Informationen, die für die Verarbeitung eines Requests nötig sind, in diesem enthalten sein müssen. Ein Beispiel dafür ist die Session-Information nach einer Anmeldung. Nicht die HTTP-Verbindung eines bestimmten Absenders oder vorangegangene Requests gestatten den Zugriff auf eine API, sondern ausschließlich die mitgesendete Session-ID.
gRPC, ...
... oder ausgeschrieben: „gRPC Remote Procedure Call“, ist ein Framework, das von Google entwickelt wurde. Als Basis für die Kommunikation dient HTTP 2.0. Diese findet nicht im „dienstleistungsorientierten Stil" wie bei REST statt, sondern auf Prozedurebene.
Eine Unterscheidung zwischen verschiedenen HTTP-Verben nutzt gRPC nicht. Stattdessen kapselt jeder RPC ein Status-Objekt, das die transportierte Nachricht und eine Liste von Status-Codes vorhält. Mögliche Codes sind beispielsweise „OK“ im Falle der 0 oder „UNAUTHENTICATED“ bei einer 16. gRPC ist ebenso stateless und sprachagnostisch wie REST. Dafür sorgt die IDL Protobuf. Ähnlich wie OpenAPI können damit Struktur und Typisierung einzelner Felder der auszutauschenden Daten dokumentiert und für Typ-, Service- und Stubgenerierung genutzt werden. Für eine API-Versionierung bietet es sich an, den Protobuf-Package-Namen in Kombination mit einem dazugehörigen Service zu verwenden. Darüber hinaus wird in der Regel nicht mit dem oben genannten Request-Response-Modell gearbeitet, sondern mit verschiedenen Arten von Streams des HTTP-2.0-Standards.
Streaming gut, alles gut?
Nicht ganz. Denn aktuell gibt es keine API, um einem Browser „vorzuschreiben“, welchen HTTP-Standard er benutzen „muss“. Dafür müsste ein direkter Zugriff auf die in HTTP-2.0 eingeführten Frames bestehen und genau das ist nicht möglich. Somit kann gRPC aktuell ohne Weiteres nicht im Browser verwendet werden wie REST. grpc-web als JavaScript-Bibliothek bietet einen Workaround mittels eines Proxys. Um ein paar Details dazu zu erklären, hier ein kleiner Exkurs:
HTTP 1.1 vs. HTTP 2.0
Wie immer das Offensichtliche vorweg: HTTP 2.0 ist neuer. Genau genommen stammt der Standard aus dem Jahr 2015, ist also noch gar nicht so alt. Ebenso ist das Problem, das man mit der Aktualisierung von HTTP lösen wollte, noch relativ jung. Durch das Vorhandensein vieler mobiler Endgeräte entstand der Bedarf, Webseiten schneller zu laden. Dies kann natürlich durch Reduktion der Größe der übertragenen Datenmenge erreicht werden, aber das eigentliche Problem, das man gelöst hat, betrifft den Übertragungsweg selbst. HTTP 1.1 überträgt Daten sequentiell in Form von Requests, die in einer Queue pro Connection eingereiht werden. Dank der Ablösung von HTTP 1.0 gibt es zwar mehrere Verbindungen, dennoch sind diese in der Anzahl relativ begrenzt und der Neuaufbau ist rechenintensiv. Entsprechend kann es passieren, dass die Abarbeitung der Elemente in der Queue längere Zeit benötigt, wenn die jeweils vorderen Requests nicht abgearbeitet werden können und der Seitenaufbau verzögert sich.
Dies wird allgemein als das „Head-Of-Line-Blocking“-Problem bezeichnet. Mithilfe der Einführung von uni- und bidirektionalem Streaming wird das Problem umgangen.
Darüber hinaus überträgt HTTP 2.0 den Inhalt nicht im Klartext, sondern binär in Form von Frames. In Verbindung mit der Header-Komprimierung werden die Übertragungszeiten insgesamt verringert. Im Umkehrschluss bedeutet dies natürlich, dass auch alle beteiligten Komponenten, also z. B. Browser, Client- oder Serverbibliotheken, mit HTTP 2.0 umgehen können müssen. Eine Liste von Frameworks, die HTTP 2.0 unterstützen, findet sich im GitHub-Repo der HTTPWG.
Vergleich REST und gRPC
Übersicht Eigenschaften
Eigenschaft | gRPC | REST |
---|---|---|
stateless | ja | ja |
IDL | protobuf | OpenAPI |
API-Design | RPC-style | Ressource |
Min. HTTP Version | 2.0* | 1.1 |
(*unter Verzicht auf einige Features wie z.B. Streaming ist auch die Verwendung von HTTP-1.1 machbar, siehe https://grpc.fyi/docs/interoperability) |
Performance
Bei der Nutzung von HTTP 2.0 sind durch Nutzung von Komprimierung und Streaming spürbare Performancegewinne zu erwarten. Durch die Verwendung von Protobuf kann ebenso Zeit bei der Serialisierung/Deserialisierung gespart werden, konkret nennt Microsoft „bis zu 8-mal schneller“. Auch die Verringerung der Requestgröße dürfte sich positiv auf die Performance auswirken. Diese wird verglichen mit REST mit „60-80 % kleiner“ angegeben.
Vergleich Support in Java- und Kotlin-Ökosystem
Die vermutlich größte und zumindest laut eigener Aussage beliebteste Framework-Sammlung für Java ist Spring. Für REST finden wir breite Unterstützung für alle möglichen Aufgaben, die mit einer REST-Schnittstelle in Verbindung stehen. Darüber hinaus finden sich hier auch viele weitere helfende Frameworks, die uns das Leben leichter machen. So generieren wir mithilfe von Spring REST Docs eine Dokumentation aus unseren Tests oder schreiben Contract-Tests für generierte Stubs mit Spring Cloud Contract. Auch gibt es ein Spring-Boot Starter-Projekt (spring-boot-starter-web), das uns ein breites Spektrum an Abhängigkeiten mitbringt, damit wir loslegen können.
gRPC findet dagegen keinen derart breiten Support im Spring-Universum, aber dennoch gibt es Lösungen. Eine Möglichkeit bietet Spring Cloud Gateway, wie hier beschrieben. Einen offiziellen Spring Starter zu gRPC gibt es dagegen nicht, lediglich ein im Moment etwas verstaubtes inoffizielles Projekt mit einem ähnlichen Namen: grpc-spring-boot-starter. Dies ist allerdings nicht im offiziellen GitHub-Repository in Spring gelistet und bietet aktuell keinen Support für Spring Boot 3, behandelt in Issue 953 Auch das genannte Spring Cloud Contract bietet die Möglichkeit, Schnittstellen-Tests für gRPC zu schreiben. Dieses Feature ist aktuell aber noch im Beta-Status laut den Docs Abseits von Spring finden sich dagegen Lösungen sowohl direkt von Google sowie von Quarkus für Java und Kotlin.
Zusammenfassung
Ist gRPC „das“ bessere Paradigma für Kommunikation? Das kommt darauf an. Auf dem Papier bietet gRPC eine noch schnellere Performance als REST, aber ist REST wirklich langsam? Zalando als großer Player im E-Commerce nutzt beispielsweise im eigenen Eventbroker Nakadi REST, aber plant ebenso die Unterstützung von Protobuf bzw. gRPC. Google hat bei der Entwicklung von gRPC und dazugehörigen Komponenten sicherlich noch Performance-lastigere Anwendungsfälle bedienen müssen, weshalb selbst die kleinste Optimierung absolut notwendig gewesen ist. Dabei fielen der aktuell noch fehlende Browser-Support sowie die Unterschiede in der API-Struktur vermutlich nicht ins Gewicht. Auf der technischen Ebene nutzt das eingangs erwähnte OpenTelemetry gRPC und HTTP 1.1, um möglichst breit aufgestellt zu sein. Ich persönlich habe die Erfahrung gemacht, dass weniger der Kommunikationsweg ein Problem ist als die Implementierung, welche die API konsumiert oder mit Daten versorgt. Sich dabei auf einen gängigen Mitspieler wie Spring verlassen zu können, fühlt sich gut an. Dass aber gerade dieser Faktor nicht gegeben ist, zeigt mir, dass der Schmerz, gRPC im Java-Ökosystem verwenden zu wollen, nicht ganz so groß ist. Oder, wie im Beispiel Nakadi demonstriert, der Standard gRPC noch nicht etabliert genug ist.
Weitere Beiträge
von Sebastian Tiemann
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Sebastian Tiemann
Senior API Consultant
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.