De REST API is al lange tijd een pijler van webprogrammering. Maar onlangs is gRPC begonnen met het aantasten van zijn grondgebied. Het blijkt dat daar enkele goede redenen voor zijn. In deze tutorial leer je over het reilen en zeilen van gRPC en hoe het zich verhoudt tot REST.
Een van de grootste verschillen tussen REST en gRPC is het formaat van de payload. REST-berichten bevatten meestal JSON. Dit is geen strikte vereiste, en in theorie kun je alles als reactie verzenden, maar in de praktijk is het hele REST-ecosysteem, inclusief tooling, beste praktijken en zelfstudies, gericht op JSON. Het is veilig om te zeggen dat, op enkele uitzonderingen na, REST API's JSON accepteren en retourneren.
gRPC daarentegen accepteert en retourneert Protobuf-berichten. Ik zal later de sterke typering bespreken, maar alleen vanuit het oogpunt van prestaties is Protobuf een zeer efficiënt en verpakt formaat. JSON is daarentegen een tekstformaat. Je kunt JSON comprimeren, maar dan verlies je het voordeel van een tekstindeling die je gemakkelijk kunt verwachten.
Laten we de overdrachtsprotocollen vergelijken die REST en gRPC gebruiken. REST, zoals eerder vermeld, is sterk afhankelijk van HTTP (meestal HTTP 1.1) en het request-response-model. Aan de andere kant gebruikt gRPC het nieuwere HTTP / 2-protocol.
Er zijn verschillende problemen die HTTP 1.1 teisteren die HTTP / 2-fixes. Dit zijn de belangrijkste.
HTTP 1.0 RFC 1945 is een RFC van 60 pagina's. HTTP 1.1 is oorspronkelijk beschreven in RFC 2616, die tot 176 pagina's heeft opgeblazen. Later deelde de IETF het echter op in zes verschillende documenten - RFC 7230, 7231, 7232, 7233, 7234 en 7235 - met een nog hoger gecombineerd aantal pagina's. HTTP 1.1 maakt veel optionele onderdelen mogelijk die bijdragen aan de grootte en complexiteit.
De trend van webpagina's is om zowel de totale grootte van de pagina (gemiddeld 1,9 MB) als het aantal objecten op de pagina die individuele verzoeken vereisen, te vergroten. Aangezien elk object een afzonderlijk HTTP-verzoek vereist, neemt deze vermenigvuldiging van afzonderlijke objecten de belasting van webservers aanzienlijk toe en worden laadtijden van pagina's voor gebruikers vertraagd.
HTTP 1.1 is gevoelig voor latentie. Een TCP-handshake is vereist voor elk individueel verzoek en een groter aantal aanvragen vraagt een aanzienlijke tol van de tijd die nodig is om een pagina te laden. De voortdurende verbetering van de beschikbare bandbreedte lost deze latentieproblemen in de meeste gevallen niet op.
De beperking van het aantal verbindingen met hetzelfde domein (vroeger slechts 2, vandaag 6-8) vermindert aanzienlijk de mogelijkheid om meerdere verzoeken tegelijkertijd te verzenden.
Met HTTP pipelining kunt u een verzoek verzenden in afwachting van het antwoord op een eerder verzoek, waardoor u in feite een wachtrij maakt. Maar dat introduceert andere problemen. Als uw verzoek achterloopt op een traag verzoek, zal uw reactietijd eronder lijden.
Er zijn nog andere problemen, zoals prestaties en bronboetes bij het overschakelen van lijnen. Op dit moment is HTTP pipelining niet breed ingeschakeld.
HTTP / 2, afkomstig van de SPDY van Google, onderhoudt de basisprincipes en paradigma's van HTTP:
http: //
en https: //
URL-schema'sMaar de optionele delen van HTTP 1.1 zijn verwijderd.
Om het onderhandelingsprotocol aan te pakken vanwege het gedeelde URL-schema, is er een upgrade-header. Ook is hier een shocker voor u: het HTTP / 2-protocol is binair! Als u al eens rond internetprotocollen bent geweest, weet u dat tekstuele protocollen als 'koning' worden beschouwd omdat het voor mensen eenvoudiger is om handmatig problemen op te lossen en aanvragen op te stellen. Maar in de praktijk gebruiken de meeste servers tegenwoordig encryptie en compressie. De binaire framing gaat een lange weg naar het verminderen van de complexiteit van het verwerken van frames in HTTP 1.1.
De belangrijkste verbetering van HTTP / 2 is echter dat het multiplex-streams gebruikt. Een enkele HTTP / 2 TCP-verbinding kan vele bidirectionele streams ondersteunen. Deze streams kunnen worden doorschoten (geen wachtrijen) en er kunnen meerdere verzoeken tegelijk worden verzonden zonder dat er voor elk een nieuwe TCP-verbinding hoeft te worden gemaakt. Bovendien kunnen servers nu meldingen verzenden naar clients via de bestaande verbinding (HTTP / 2 push).
REST is een interessante API. Het is erg strak bovenop HTTP gebouwd. Het gebruikt HTTP niet alleen als een transport, maar omvat alle functies en bouwt er een consistent conceptueel kader bovenop. In theorie klinkt het geweldig. In de praktijk was het erg moeilijk om REST correct te implementeren.
Begrijp me niet verkeerd: REST was en is zeer succesvol, maar de meeste implementaties houden niet volledig vast aan de REST-filosofie en gebruiken slechts een deel van de principes. De reden is dat het eigenlijk best uitdagend is om zakelijke logica en bewerkingen in de strikte REST-wereld in kaart te brengen.
Het conceptuele model dat wordt gebruikt door gRPC is om services te hebben met duidelijke interfaces en gestructureerde berichten voor verzoeken en antwoorden. Dit model vertaalt zich direct uit programmeertaalconcepten zoals interfaces, functies, methoden en gegevensstructuren. Het maakt het ook mogelijk dat gRPC automatisch clientbibliotheken voor u genereert.
REST ondersteunt alleen het request-response-model dat beschikbaar is in HTTP 1.x. Maar gRPC maakt optimaal gebruik van de mogelijkheden van HTTP / 2 en stelt u in staat informatie constant te streamen. Er zijn verschillende soorten streaming.
De server stuurt een stroom van antwoorden terug na het ontvangen van een verzoek om een client. Na het terugsturen van alle antwoorden worden de statusgegevens van de server en optionele metagegevens over de server teruggestuurd om te voltooien aan de serverzijde. De client voltooit zodra alle antwoorden van de server zijn ontvangen.
De client verzendt een stroom van meerdere verzoeken naar de server. De server stuurt één antwoord terug, meestal maar niet noodzakelijk nadat alle verzoeken van de klant zijn ontvangen, samen met de statusdetails en optionele nalopende metadata..
In dit scenario verzenden de client en de server vrijwel in vrije vorm informatie naar elkaar (behalve dat de client de reeks initieert). Uiteindelijk sluit de client de verbinding.
Het REST-paradigma verplicht geen structuur voor de uitgewisselde payload. Het is typisch JSON. Consumenten hebben geen formeel mechanisme om het formaat van verzoeken en antwoorden te coördineren. De JSON moet worden geserialiseerd en worden geconverteerd naar de doeltaal, zowel aan de serverzijde als aan de clientzijde. De serialisatie is een nieuwe stap in de keten die de mogelijkheid van fouten en prestatieoverhead introduceert.
Het gRPC-servicecontract heeft sterk getypte berichten die automatisch worden omgezet van hun Protobuf-weergave naar uw programmeertaal naar keuze, zowel op de server als op de client.
JSON daarentegen is in theorie flexibeler omdat je dynamische gegevens kunt verzenden en niet hoeft vast te houden aan een rigide structuur.
Ondersteuning voor gRPC in de browser is niet zo volwassen. Tegenwoordig wordt gRPC voornamelijk gebruikt voor interne diensten die niet rechtstreeks aan de wereld worden blootgesteld.
Als u een gRPC-service wilt gebruiken van een webtoepassing of van een taal die niet wordt ondersteund door gRPC, biedt gRPC een REST API-gateway om uw service bloot te leggen. De gRPC gateway-plug-in genereert een volwaardige REST API-server met een omgekeerde proxy- en Swagger-documentatie.
Met deze aanpak verliest u de meeste voordelen van gRPC, maar als u toegang tot een bestaande service moet bieden, kunt u dit doen zonder uw service twee keer te implementeren.
In de wereld van microservices zal gRPC zeer snel dominant worden. De prestatie-voordelen en het gemak van ontwikkeling zijn gewoon te goed om te laten liggen. Vergis je echter niet, REST zal nog lang aanwezig zijn. Het blinkt nog steeds uit voor publiekelijk getoonde API's en om redenen van achterwaartse compatibiliteit.