gRPC vs. REST: Noțiuni introductive cu cel mai bun protocol API
Publicat: 2022-07-22În peisajul tehnologic de astăzi, majoritatea proiectelor necesită utilizarea API-urilor. API-urile unesc comunicarea între servicii care pot reprezenta un singur sistem complex, dar pot locui și pe mașini separate sau pot folosi mai multe rețele sau limbi incompatibile.
Multe tehnologii standard se adresează nevoilor de comunicare interservicii ale sistemelor distribuite, cum ar fi REST, SOAP, GraphQL sau gRPC. În timp ce REST este o abordare favorizată, gRPC este un candidat demn, oferind performanțe înalte, contracte tipizate și instrumente excelente.
Prezentare generală REST
Transferul de stat reprezentativ (REST) este un mijloc de preluare sau manipulare a datelor unui serviciu. O API REST este în general construită pe protocolul HTTP, folosind un URI pentru a selecta o resursă și un verb HTTP (de exemplu, GET, PUT, POST) pentru a selecta operația dorită. Corpurile de solicitare și de răspuns conțin date care sunt specifice operațiunii, în timp ce anteturile lor oferă metadate. Pentru a ilustra, să ne uităm la un exemplu simplificat de preluare a unui produs prin intermediul unui API REST.
Aici, solicităm o resursă de produs cu un ID de 11
și direcționăm API-ului să răspundă în format JSON:
GET /products/11 HTTP/1.1 Accept: application/json
Având în vedere această solicitare, răspunsul nostru (anteturi irelevante omise) poate arăta astfel:
HTTP/1.1 200 OK Content-Type: application/json { id: 11, name: "Purple Bowtie", sku: "purbow", price: { amount: 100, currencyCode: "USD" } }
Deși JSON poate fi citit de om, nu este optim atunci când este utilizat între servicii. Natura repetitivă a referințelor numelor de proprietăți – chiar și atunci când sunt comprimate – poate duce la mesaje umflate. Să ne uităm la o alternativă pentru a aborda această problemă.
Prezentare generală a gRPC
gRPC Remote Procedure Call (gRPC) este un protocol de comunicare open-source, bazat pe contract, multiplatformă, care simplifică și gestionează comunicarea interservicii prin expunerea unui set de funcții clienților externi.
Construit pe baza HTTP/2, gRPC folosește funcții precum streaming bidirecțional și Transport Layer Security (TLS) încorporat. gRPC permite o comunicare mai eficientă prin încărcături binare serializate. Folosește în mod implicit tampon de protocol ca mecanism pentru serializarea datelor structurate, similar cu utilizarea JSON de către REST.
Spre deosebire de JSON, totuși, bufferele de protocol sunt mai mult decât un format serializat. Acestea includ alte trei părți majore:
- Un limbaj de definire a contractului găsit în fișierele
.proto
(Vom urma proto3, cea mai recentă specificație pentru limbajul tampon al protocolului.) - Codul funcției de accesorii generat
- Biblioteci de rulare specifice limbii
Funcțiile de la distanță care sunt disponibile pe un serviciu (definite într-un fișier .proto
) sunt listate în interiorul nodului de serviciu în fișierul tampon de protocol. În calitate de dezvoltatori, ajungem să definim aceste funcții și parametrii lor folosind sistemul de tip bogat al bufferelor de protocol. Acest sistem acceptă diverse tipuri numerice și de date, liste, dicționare și numere nula pentru a defini mesajele noastre de intrare și de ieșire.
Aceste definiții de servicii trebuie să fie disponibile atât pentru server, cât și pentru client. Din păcate, nu există un mecanism implicit pentru a partaja aceste definiții în afară de furnizarea de acces direct la fișierul .proto
în sine.
Acest exemplu de fișier .proto
definește o funcție pentru a returna o intrare de produs, având un ID:
Tastarea strictă și ordonarea câmpurilor a proto3 fac ca deserializarea mesajelor să fie considerabil mai puțin dificilă decât analizarea JSON.
Compararea REST cu gRPC
Pentru a recapitula, cele mai semnificative puncte când se compară REST cu gRPC sunt:
ODIHNĂ | gRPC | |
---|---|---|
Multiplatformă | da | da |
Format mesaj | Personalizat, dar în general JSON sau XML | tampon de protocol |
Dimensiunea încărcăturii mesajului | Mediu/Mare | Mic |
Complexitatea procesării | Mai mare (analizarea textului) | Inferioară (structură binară bine definită) |
Suport pentru browser | Da (nativ) | Da (prin gRPC-Web) |
Acolo unde sunt de așteptat contracte mai puțin stricte și completări frecvente la sarcina utilă, JSON și REST se potrivesc perfect. Când contractele tind să rămână mai statice și viteza este de cea mai mare importanță, gRPC câștigă în general. În majoritatea proiectelor la care am lucrat, gRPC s-a dovedit a fi mai ușor și mai performant decât REST.
Implementarea serviciului gRPC
Să construim un proiect simplificat pentru a explora cât de simplu este să adoptați gRPC.
Crearea proiectului API
Pentru a începe, vom crea un proiect .NET 6 în Visual Studio 2022 Community Edition (VS). Vom selecta șablonul ASP.NET Core gRPC Service și vom numi atât proiectul (vom folosi InventoryAPI
) cât și prima noastră soluție din cadrul acestuia ( Inventory
) .
Acum, să alegem . Opțiunea NET 6.0 (suport pe termen lung) pentru cadrul nostru:
Definirea serviciului nostru de produse
Acum că am creat proiectul, VS afișează un exemplu de serviciu de definire a prototipului gRPC numit Greeter
. Vom reutiliza fișierele de bază ale lui Greeter
pentru a se potrivi nevoilor noastre.
- Pentru a crea contractul nostru, vom înlocui conținutul
greet.proto
cu fragmentul 1, redenumind fișierulproduct.proto
. - Pentru a crea serviciul nostru, vom înlocui conținutul fișierului
GreeterService.cs
cu Snippet 2, redenumind fișierulProductCatalogService.cs
.
Serviciul returnează acum un produs codificat. Pentru ca serviciul să funcționeze, trebuie doar să modificăm înregistrarea serviciului în Program.cs
pentru a face referire la noul nume al serviciului. În cazul nostru, vom redenumi app.MapGrpcService<GreeterService>();
la app.MapGrpcService<ProductCatalogService>();
pentru a face rulabil noul nostru API.
Avertisment corect: nu este testul dvs. standard de protocol
Deși putem fi tentați să-l încercăm, nu putem testa serviciul nostru gRPC printr-un browser care vizează punctul final al acestuia. Dacă ar fi să încercăm acest lucru, am primi un mesaj de eroare care indică faptul că comunicarea cu punctele finale gRPC trebuie făcută printr-un client gRPC.
Crearea Clientului
Pentru a testa serviciul nostru, să folosim șablonul de bază Console App al VS și să creăm un client gRPC pentru a apela API-ul. Mi-am numit InventoryApp
.
Pentru comoditate, să facem referire la o cale relativă a fișierului prin care ne vom împărtăși contractul. Vom adăuga manual referința în fișierul .csproj
. Apoi, vom actualiza calea și vom seta modul Client
. Notă: vă recomand să vă familiarizați cu structura locală a folderelor și să aveți încredere în aceasta înainte de a utiliza referirea relativă.
Iată referințele .proto
, așa cum apar atât în fișierele de proiect ale serviciului, cât și ale clientului:
Fișier proiect de serviciu (Cod de copiat în fișierul proiectului client) | Fișier proiect client (După lipire și editare) |
---|---|
|
|
Acum, pentru a apela serviciul nostru, vom înlocui conținutul Program.cs
. Codul nostru va îndeplini o serie de obiective:
- Creați un canal care să reprezinte locația punctului final al serviciului (portul poate varia, deci consultați fișierul
launchsettings.json
pentru valoarea reală). - Creați obiectul client.
- Construiți o cerere simplă.
- Trimite cererea.
Pregătirea pentru lansare
Pentru a testa codul nostru, în VS, vom face clic dreapta pe soluție și vom alege Set Startup Projects . În dialogul Pagini de proprietăți ale soluției, vom:
- Selectați butonul radio de lângă Proiecte de pornire multiple și, în meniul drop-down Acțiune, setați ambele proiecte (
InventoryAPI
șiInventoryApp
) la Start . - Faceți clic pe OK .
Acum putem porni soluția făcând clic pe Start în bara de instrumente VS (sau apăsând tasta F5 ). Se vor afișa două ferestre noi de consolă: una pentru a ne spune că serviciul ascultă, cealaltă pentru a ne arăta detaliile produsului preluat.
Partajarea contractului gRPC
Acum să folosim o altă metodă pentru a conecta clientul gRPC la definiția serviciului nostru. Cea mai accesibilă soluție de partajare a contractelor este să punem la dispoziție definițiile noastre printr-o adresă URL. Alte opțiuni sunt fie foarte fragile (fișier partajat printr-o cale), fie necesită mai mult efort (contract partajat printr-un pachet nativ). Partajarea printr-o adresă URL (cum fac SOAP și Swagger/OpenAPI) este flexibilă și necesită mai puțin cod.
Pentru a începe, faceți fișierul .proto
disponibil ca conținut static. Vom actualiza codul manual, deoarece interfața de utilizare pentru acțiunea de construire este setată la „Compilatorul Protobuf”. Această modificare direcționează compilatorul să copieze fișierul .proto
, astfel încât să poată fi servit de la o adresă web. Dacă această setare ar fi schimbată prin VS UI, construcția s-ar rupe. Primul nostru pas este să adăugăm fragmentul 4 la fișierul InventoryAPI.csproj
:
Apoi, inserăm codul în fragmentul 5 din partea de sus a fișierului ProductCatalogService.cs
pentru a configura un punct final pentru a returna fișierul nostru .proto
:
Și acum, adăugăm fragmentul 6 chiar înainte de app.Run()
, tot în fișierul ProductCatalogService.cs
:
Cu fragmentele 4-6 adăugate, conținutul fișierului .proto
ar trebui să fie vizibil în browser.
Un nou client de testare
Acum dorim să creăm un nou client de consolă pe care îl vom conecta la serverul nostru existent cu Dependency Wizard al VS. Problema este că acest expert nu vorbește HTTP/2. Prin urmare, trebuie să ne adaptăm serverul pentru a vorbi prin HTTP/1 și să pornim serverul. Cu serverul nostru care își pune acum la dispoziție fișierul .proto
, putem construi un nou client de testare care se conectează la serverul nostru prin vrăjitorul gRPC.
- Pentru a schimba serverul nostru pentru a vorbi prin HTTP/1, vom edita fișierul JSON
appsettings.json
:- Ajustați câmpul
Protocol
(găsit la caleaKestrel.EndpointDefaults.Protocols
) pentru a citiHttps
. - Salvați fișierul.
- Ajustați câmpul
- Pentru ca noul nostru client să citească aceste informații
proto
, serverul trebuie să ruleze. Inițial, am pornit atât clientul anterior, cât și serverul nostru din dialogul VS Set Startup Projects. Ajustați soluția de server pentru a începe doar proiectul de server, apoi porniți soluția. (Acum că am modificat versiunea HTTP, vechiul nostru client nu mai poate comunica cu serverul.) - Apoi, creați noul client de testare. Lansați o altă instanță a VS. Vom repeta pașii așa cum este detaliat în secțiunea Crearea proiectului API , dar de data aceasta, vom alege șablonul Aplicație Console . Vom numi proiectul și soluția noastră
InventoryAppConnected
. - Cu șasiul client creat, ne vom conecta la serverul nostru gRPC. Extindeți noul proiect în VS Solution Explorer.
- Faceți clic dreapta pe Dependențe și, în meniul contextual, selectați Gestionare servicii conectate .
- În fila Servicii conectate, faceți clic pe Adăugați o referință de serviciu și alegeți gRPC .
- În caseta de dialog Adăugați referință la serviciu, alegeți opțiunea URL și introduceți versiunea
http
a adresei serviciului (nu uitați să luați numărul portului generat aleatoriu dinlaunchsettings.json
) . - Faceți clic pe Terminare pentru a adăuga o referință de serviciu care poate fi întreținută cu ușurință.
Simțiți-vă liber să vă verificați munca cu exemplul de cod pentru acest exemplu. Deoarece, sub capotă, VS a generat același client pe care l-am folosit în prima noastră rundă de testare, putem reutiliza conținutul fișierului Program.cs
din serviciul anterior text.
Când modificăm un contract, trebuie să modificăm definiția clientului gRPC pentru a se potrivi cu definiția .proto
actualizată. Pentru a face acest lucru, trebuie doar să accesăm Serviciile conectate ale VS și să reîmprospătăm intrarea de serviciu relevantă. Acum, proiectul nostru gRPC este finalizat și este ușor să ne menținem sincronizat serviciul și clientul.
Următorul tău candidat pentru proiect: gRPC
Implementarea noastră gRPC oferă o privire directă asupra beneficiilor utilizării gRPC. REST și gRPC au fiecare propriile cazuri de utilizare ideale, în funcție de tipul de contract. Cu toate acestea, atunci când ambele opțiuni se potrivesc, vă încurajez să încercați gRPC - vă va pune înaintea curbei în viitorul API-urilor.