gRPC vs. REST: Guida introduttiva al miglior protocollo API
Pubblicato: 2022-07-22Nel panorama tecnologico odierno, la maggior parte dei progetti richiede l'uso di API. Le API collegano la comunicazione tra servizi che possono rappresentare un unico sistema complesso ma possono anche risiedere su macchine separate o utilizzare più reti o linguaggi incompatibili.
Molte tecnologie standard soddisfano le esigenze di comunicazione tra i servizi dei sistemi distribuiti, come REST, SOAP, GraphQL o gRPC. Mentre REST è un approccio preferito, gRPC è un degno contendente, che offre prestazioni elevate, contratti digitati e strumenti eccellenti.
Panoramica REST
Il trasferimento dello stato rappresentativo (REST) è un mezzo per recuperare o manipolare i dati di un servizio. Un'API REST è generalmente costruita sul protocollo HTTP, utilizzando un URI per selezionare una risorsa e un verbo HTTP (ad esempio, GET, PUT, POST) per selezionare l'operazione desiderata. I corpi di richiesta e risposta contengono dati specifici dell'operazione, mentre le loro intestazioni forniscono metadati. Per illustrare, diamo un'occhiata a un esempio semplificato di recupero di un prodotto tramite un'API REST.
Qui, richiediamo una risorsa prodotto con un ID 11
e indirizziamo l'API a rispondere in formato JSON:
GET /products/11 HTTP/1.1 Accept: application/json
Data questa richiesta, la nostra risposta (intestazioni irrilevanti omesse) potrebbe essere simile a:
HTTP/1.1 200 OK Content-Type: application/json { id: 11, name: "Purple Bowtie", sku: "purbow", price: { amount: 100, currencyCode: "USD" } }
Sebbene JSON possa essere leggibile dall'uomo, non è ottimale se utilizzato tra i servizi. La natura ripetitiva del riferimento ai nomi delle proprietà, anche se compressi, può portare a messaggi gonfi. Diamo un'occhiata a un'alternativa per affrontare questa preoccupazione.
Panoramica di gRPC
gRPC Remote Procedure Call (gRPC) è un protocollo di comunicazione open source, basato su contratto e multipiattaforma che semplifica e gestisce la comunicazione tra servizi esponendo una serie di funzioni a client esterni.
Basato su HTTP/2, gRPC sfrutta funzionalità come lo streaming bidirezionale e il Transport Layer Security (TLS) integrato. gRPC consente una comunicazione più efficiente attraverso payload binari serializzati. Per impostazione predefinita, utilizza i buffer di protocollo come meccanismo per la serializzazione dei dati strutturati, in modo simile all'uso di JSON da parte di REST.
A differenza di JSON, tuttavia, i buffer di protocollo sono più di un formato serializzato. Includono altre tre parti principali:
- Un linguaggio di definizione del contratto che si trova nei file
.proto
(seguiremo proto3, l'ultima specifica del linguaggio del buffer del protocollo). - Codice funzione di accesso generato
- Librerie di runtime specifiche della lingua
Le funzioni remote disponibili su un servizio (definite in un file .proto
) sono elencate all'interno del nodo del servizio nel file buffer del protocollo. In qualità di sviluppatori, possiamo definire queste funzioni ei loro parametri utilizzando il sistema di tipi avanzati dei buffer di protocollo. Questo sistema supporta vari tipi numerici e di data, elenchi, dizionari e valori nullable per definire i nostri messaggi di input e output.
Queste definizioni di servizio devono essere disponibili sia per il server che per il client. Sfortunatamente, non esiste un meccanismo predefinito per condividere queste definizioni oltre a fornire l'accesso diretto al file .proto
stesso.
Questo file .proto
di esempio definisce una funzione per restituire una voce di prodotto, dato un ID:
La digitazione rigorosa e l'ordinamento dei campi di proto3 rendono la deserializzazione dei messaggi notevolmente meno gravosa rispetto all'analisi di JSON.
Confronto tra REST e gRPC
Per ricapitolare, i punti più significativi nel confronto tra REST e gRPC sono:
RIPOSO | gRPC | |
---|---|---|
Multipiattaforma | sì | sì |
Formato messaggio | Personalizzato ma generalmente JSON o XML | Buffer di protocollo |
Dimensione del carico utile del messaggio | Medio grande | Piccolo |
Complessità di elaborazione | Superiore (analisi del testo) | Inferiore (struttura binaria ben definita) |
Supporto del browser | Sì (nativo) | Sì (tramite gRPC-Web) |
Laddove sono previsti contratti meno rigidi e frequenti aggiunte al carico utile, JSON e REST sono ottime soluzioni. Quando i contratti tendono a rimanere più statici e la velocità è della massima importanza, gRPC generalmente vince. Nella maggior parte dei progetti su cui ho lavorato, gRPC si è dimostrato più leggero e più performante di REST.
Implementazione del servizio gRPC
Costruiamo un progetto semplificato per esplorare quanto sia semplice adottare gRPC.
Creazione del progetto API
Per iniziare, creeremo un progetto .NET 6 in Visual Studio 2022 Community Edition (VS). Selezioneremo il modello di servizio gRPC ASP.NET Core e nomineremo sia il progetto (usare InventoryAPI
) sia la nostra prima soluzione al suo interno ( Inventory
) .
Ora scegliamo il . Opzione NET 6.0 (supporto a lungo termine) per il nostro framework:
Definizione del nostro servizio di prodotto
Ora che abbiamo creato il progetto, VS mostra un servizio di definizione prototipo gRPC di esempio denominato Greeter
. Riutilizzeremo i file principali di Greeter
per soddisfare le nostre esigenze.
- Per creare il nostro contratto, sostituiremo il contenuto di
greet.proto
con Snippet 1, rinominando il fileproduct.proto
. - Per creare il nostro servizio, sostituiremo il contenuto del file
GreeterService.cs
con Snippet 2, rinominando il fileProductCatalogService.cs
.
Il servizio ora restituisce un prodotto hardcoded. Per far funzionare il servizio, è sufficiente modificare la registrazione del servizio in Program.cs
per fare riferimento al nuovo nome del servizio. Nel nostro caso, rinomineremo app.MapGrpcService<GreeterService>();
ad app.MapGrpcService<ProductCatalogService>();
per rendere eseguibile la nostra nuova API.
Avviso corretto: non il test del protocollo standard
Anche se potremmo essere tentati di provarlo, non possiamo testare il nostro servizio gRPC tramite un browser puntato al suo endpoint. Se dovessimo tentare questa operazione, riceveremmo un messaggio di errore che indica che la comunicazione con gli endpoint gRPC deve essere effettuata tramite un client gRPC.
Creazione del cliente
Per testare il nostro servizio, utilizziamo il modello di base dell'app Console di VS e creiamo un client gRPC per chiamare l'API. Ho chiamato la mia InventoryApp
.
Per convenienza, facciamo riferimento a un relativo percorso di file attraverso il quale condivideremo il nostro contratto. Aggiungeremo manualmente il riferimento al file .csproj
. Quindi, aggiorneremo il percorso e imposteremo la modalità Client
. Nota: ti consiglio di acquisire familiarità e di avere fiducia nella struttura della tua cartella locale prima di utilizzare il riferimento relativo.
Di seguito sono riportati i riferimenti .proto
, come appaiono sia nel servizio che nei file di progetto del client:
File di progetto di servizio (Codice da copiare nel file di progetto del cliente) | File di progetto del cliente (Dopo aver incollato e modificato) |
---|---|
|
|
Ora, per chiamare il nostro servizio, sostituiremo i contenuti di Program.cs
. Il nostro codice raggiungerà una serie di obiettivi:
- Crea un canale che rappresenti la posizione dell'endpoint del servizio (la porta può variare, quindi consulta il file
launchsettings.json
per il valore effettivo). - Crea l'oggetto client.
- Costruisci una semplice richiesta.
- Invia la richiesta.
Preparazione per il lancio
Per testare il nostro codice, in VS, faremo clic con il pulsante destro del mouse sulla soluzione e sceglieremo Set Startup Projects . Nella finestra di dialogo Pagine delle proprietà della soluzione:
- Seleziona il pulsante di opzione accanto a Più progetti di avvio e, nel menu a discesa Azione, imposta entrambi i progetti (
InventoryAPI
eInventoryApp
) su Start . - Fare clic su OK .
Ora possiamo avviare la soluzione facendo clic su Avvia nella barra degli strumenti VS (o premendo il tasto F5 ). Verranno visualizzate due nuove finestre della console: una per dirci che il servizio è in ascolto, l'altra per mostrarci i dettagli del prodotto recuperato.
Condivisione del contratto gRPC
Ora utilizziamo un altro metodo per connettere il client gRPC alla definizione del nostro servizio. La soluzione di condivisione del contratto più accessibile al cliente consiste nel rendere disponibili le nostre definizioni tramite un URL. Altre opzioni sono molto fragili (file condiviso tramite un percorso) o richiedono uno sforzo maggiore (contratto condiviso tramite un pacchetto nativo). La condivisione tramite un URL (come fanno SOAP e Swagger/OpenAPI) è flessibile e richiede meno codice.
Per iniziare, rendi disponibile il file .proto
come contenuto statico. Aggiorneremo il nostro codice manualmente perché l'interfaccia utente nell'azione di compilazione è impostata su "Protobuf Compiler". Questa modifica indica al compilatore di copiare il file .proto
in modo che possa essere servito da un indirizzo Web. Se questa impostazione venisse modificata tramite l'interfaccia utente di VS, la build verrebbe interrotta. Il nostro primo passo, quindi, è aggiungere Snippet 4 al file InventoryAPI.csproj
:
Successivamente, inseriamo il codice nello Snippet 5 nella parte superiore del file ProductCatalogService.cs
per configurare un endpoint per restituire il nostro file .proto
:
E ora aggiungiamo Snippet 6 appena prima app.Run()
, anche nel file ProductCatalogService.cs
:
Con gli Snippet 4-6 aggiunti, il contenuto del file .proto
dovrebbe essere visibile nel browser.
Un nuovo cliente di prova
Ora vogliamo creare un nuovo client console che collegheremo al nostro server esistente con la procedura guidata delle dipendenze di VS. Il problema è che questa procedura guidata non parla HTTP/2. Pertanto, dobbiamo regolare il nostro server per parlare su HTTP/1 e avviare il server. Con il nostro server che ora rende disponibile il suo file .proto
, possiamo creare un nuovo client di prova che si collega al nostro server tramite la procedura guidata gRPC.
- Per cambiare il nostro server in modo che parli su HTTP/1, modificheremo il nostro file JSON
appsettings.json
:- Regola il campo
Protocol
(che si trova nel percorsoKestrel.EndpointDefaults.Protocols
) per leggereHttps
. - Salva il file.
- Regola il campo
- Affinché il nostro nuovo client possa leggere queste informazioni
proto
, il server deve essere in esecuzione. Inizialmente, abbiamo avviato sia il client precedente che il nostro server dalla finestra di dialogo Imposta progetti di avvio di VS. Regola la soluzione server per avviare solo il progetto server, quindi avvia la soluzione. (Ora che abbiamo modificato la versione HTTP, il nostro vecchio client non può più comunicare con il server.) - Quindi, crea il nuovo client di prova. Avvia un'altra istanza di VS. Ripeteremo i passaggi descritti in dettaglio nella sezione Creazione del progetto API , ma questa volta sceglieremo il modello dell'app Console . Chiameremo il nostro progetto e la nostra soluzione
InventoryAppConnected
. - Con lo chassis del client creato, ci collegheremo al nostro server gRPC. Espandi il nuovo progetto in VS Solution Explorer.
- Fare clic con il pulsante destro del mouse su Dipendenze e, nel menu di scelta rapida, selezionare Gestisci servizi connessi .
- Nella scheda Servizi connessi, fai clic su Aggiungi un riferimento al servizio e scegli gRPC .
- Nella finestra di dialogo Aggiungi riferimento al servizio, scegli l'opzione URL e inserisci la versione
http
dell'indirizzo del servizio (ricorda di prendere il numero di porta generato casualmente dalaunchsettings.json
) . - Fare clic su Fine per aggiungere un riferimento al servizio che può essere gestito facilmente.
Sentiti libero di confrontare il tuo lavoro con il codice di esempio per questo esempio. Poiché, sotto il cofano, VS ha generato lo stesso client che abbiamo utilizzato nel nostro primo ciclo di test, possiamo riutilizzare il contenuto del file Program.cs
dal servizio precedente alla lettera.
Quando modifichiamo un contratto, dobbiamo modificare la nostra definizione di client gRPC in modo che corrisponda alla definizione .proto
aggiornata. Per fare ciò, dobbiamo solo accedere ai servizi connessi di VS e aggiornare la voce del servizio pertinente. Ora il nostro progetto gRPC è completo ed è facile mantenere sincronizzati il nostro servizio e il nostro client.
Il tuo prossimo candidato al progetto: gRPC
La nostra implementazione di gRPC offre uno sguardo in prima persona sui vantaggi dell'utilizzo di gRPC. REST e gRPC hanno ciascuno i propri casi d'uso ideali a seconda del tipo di contratto. Tuttavia, quando entrambe le opzioni si adattano, ti incoraggio a provare gRPC: ti metterà in testa alla curva nel futuro delle API.