La tec­no­lo­gia di rete continua a fare passi da gigante. Per sod­di­sfa­re le crescenti esigenze all’interno dei sistemi in­for­ma­ti­ci di­stri­bui­ti, per le Remote Procedure Calls è stato svi­lup­pa­to un nuovo sistema de­no­mi­na­to gRPC. La “g” iniziale sta per Google, che ha fornito un con­tri­bu­to de­ter­mi­nan­te allo sviluppo di questa soluzione. In questo articolo spie­ghia­mo cos’è gRPC, come funziona e dove viene uti­liz­za­to.

Cos’è gRPC?

gRPC è un moderno sistema di remote procedure call che, grazie a tecniche di processo in­no­va­ti­ve, rende possibile una co­mu­ni­ca­zio­ne par­ti­co­lar­men­te ef­fi­cien­te all’interno delle ar­chi­tet­tu­re client-server di­stri­bui­te. Come il pre­de­ces­so­re RPC, anche gRPC agisce a livello di processo. Ca­rat­te­ri­sti­ca di­stin­ti­va della co­mu­ni­ca­zio­ne in­ter­pro­ces­so tramite gRPC è il principio della tra­spa­ren­za: la col­la­bo­ra­zio­ne di istanze (talvolta molto) lontane è talmente stretta e fluida che non si avverte alcuna dif­fe­ren­za rispetto a una co­mu­ni­ca­zio­ne locale tra processi interni alla stessa macchina.

Il sistema gRPC è stato ini­zial­men­te svi­lup­pa­to da Google nel 2015. Oggi la Cloud Native Computing Foun­da­tion svolge un ruolo di primo piano nella dif­fu­sio­ne e nel per­fe­zio­na­men­to di questa tecnica di co­mu­ni­ca­zio­ne. Il sistema gRPC è di tipo open source, vale a dire che il testo sorgente è ac­ces­si­bi­le a tutti ed eventuali modifiche e migliorie del codice da parte di terzi sono non solo con­sen­ti­te, ma au­spi­ca­bi­li.

Il trasporto dei flussi di dati tra computer distanti gli uni dagli altri è ef­fet­tua­to so­li­ta­men­te da gRPC tramite pro­to­col­lo HTTP/2, mentre la strut­tu­ra­zio­ne e l’ela­bo­ra­zio­ne dei dati sono affidate a buffer di pro­to­col­lo. Questi ultimi sono salvati sotto forma di semplici file di testo con l’esten­sio­ne .proto.

gRPC è spesso definito come framework. Un framework si con­trad­di­stin­gue per il fatto che mette a di­spo­si­zio­ne degli svi­lup­pa­to­ri una cornice di pro­gram­ma­zio­ne, facendo così ri­spar­mia­re tempo e lavoro. L’im­pal­ca­tu­ra standard di gRPC contiene infatti già diverse funzioni ed elementi che non devono essere ri­pro­gram­ma­ti ogni volta ex novo. Il framework gRPC definisce inoltre in­ter­fac­ce stan­dar­diz­za­te per de­ter­mi­na­te origini (ad es. banche dati).

Come funziona gRPC: po­li­glot­ta ed ef­fi­cien­te grazie a buffer di pro­to­col­lo e HTTP/2

Nel sistema gRPC, i buffer di pro­to­col­lo (Protobuf) svolgono mol­te­pli­ci funzioni: fungono da Interface De­fi­ni­tion Language (lin­guag­gio di de­fi­ni­zio­ne dell’in­ter­fac­cia, IDL) e de­scri­vo­no un’in­ter­fac­cia in modo in­di­pen­den­te dal lin­guag­gio. Non sono pertanto legati a un lin­guag­gio di pro­gram­ma­zio­ne specifico (ad esempio Java o C). Inoltre de­fi­ni­sco­no i servizi da uti­liz­za­re e le funzioni rese di­spo­ni­bi­li. Per ciascuna funzione è possibile spe­ci­fi­ca­re quali parametri vengono inviati con una richiesta e quale valore di risposta ci si può aspettare.

Dalla pro­spet­ti­va della co­mu­ni­ca­zio­ne remota, i buffer di pro­to­col­lo rap­pre­sen­ta­no il formato fon­da­men­ta­le di in­ter­scam­bio di messaggi, che definisce le strutture, le tipologie e gli oggetti dei messaggi. I messaggi per­met­to­no al client e al server di “capirsi” e di operare come un’unica unità fun­zio­na­le e quanto più possibile ef­fi­cien­te anche a grandi distanze.

Nel caso di una richiesta a una banca dati (ad es. “Ricerca la di­spo­ni­bi­li­tà dell’articolo a magazzino”), l’ese­cu­zio­ne di una chiamata gRPC si presenta nel modo seguente:

  • prima che la ricerca possa essere ef­fet­ti­va­men­te elaborata, sono ne­ces­sa­rie alcune ope­ra­zio­ni pre­pa­ra­to­rie. Sul lato server vengono dapprima im­ple­men­ta­ti, sulla base del buffer di pro­to­col­lo, un servizio e un server gRPC. Il client ri­chie­den­te genera da parte sua uno stub adatto. Quando lo stub è di­spo­ni­bi­le, l’ap­pli­ca­zio­ne client richiama la funzione cor­ri­spon­den­te (“Query di ricerca della di­spo­ni­bi­li­tà articolo”) nello stub.
  • Suc­ces­si­va­men­te, la richiesta viene inviata al server tramite la rete. Dopo avere ricevuto la richiesta con l’ausilio di un’opportuna in­ter­fac­cia di servizio, il server gRPC avvia la ricerca vera e propria del prodotto nella banca dati.
  • In seguito, il server invia la risposta al client stub, che inoltra il valore di risposta all’istanza ri­chie­den­te iniziale (ad es. “Numero degli articoli trovati”).

Le ap­pli­ca­zio­ni sul lato client e server possono essere scritte con linguaggi di pro­gram­ma­zio­ne diversi. gRPC supera queste li­mi­ta­zio­ni grazie a in­ter­fac­ce e mec­ca­ni­smi di tra­du­zio­ne speciali.

Per il trasporto di andata e ritorno dei flussi di dati tra le macchine (proto request e proto response), HTTP/2 viene integrato in speciali pro­to­col­li di rete come TCP/IP o UDP/IP. Gli stream tra­sfe­ri­sco­no dati binari compatti, che vengono creati nell’ambito della se­ria­liz­za­zio­ne (mar­shal­ling) tipica per le chiamate di procedura remote. Affinché le strutture di dati to­tal­men­te astratte possano essere elaborate sul lato client e server in ulteriori passaggi, il messaggio trasmesso viene in seguito de­se­ria­liz­za­to (un­mar­shal­ling).

Il workflow gRPC e i primi passaggi tramite buffer di pro­to­col­lo

Il workflow gRPC si articola ti­pi­ca­men­te in quattro passaggi:

  1. De­fi­ni­zio­ne del contratto di servizi per la co­mu­ni­ca­zio­ne in­ter­pro­ces­so: vengono definiti i servizi da creare nonché i parametri fon­da­men­ta­li e le tipologie di risposta che possono essere ri­chia­ma­ti in remoto.
  2. Ge­ne­ra­zio­ne del codice gRPC dal file .proto: speciali com­pi­la­to­ri (strumenti riga di comando detti "protoc") generano, a partire da file .proto salvati, il codice operativo con le classi cor­ri­spon­den­ti per il lin­guag­gio di de­sti­na­zio­ne de­si­de­ra­to (ad es. C++, Java).
  3. Im­ple­men­ta­zio­ne dei servizi nel lin­guag­gio scelto.
  4. Creazione del client stub che richiama il servizio; suc­ces­si­va­men­te la richiesta o le richieste vengono elaborate tramite server e client.

Nel caso di una query su banca dati con la quale si ricerca un prodotto a magazzino (inventory), i primi passaggi concreti nella sintassi effettiva dei buffer di pro­to­col­lo (versione: proto3) si pre­sen­ta­no nel modo seguente:

syntax = "proto3";
package grpc_service;
import "google/protobuf/wrappers.proto";
service InventoryService {
	rpc getItemByName(google.protobuf.StringValue) returns (Items);
	rpc getItemByID(google.protobuf.StringValue) returns (Item);
	 rpc addItem(Item) returns (google.protobuf.BoolValue);
}
 
message Items {
  string itemDesc = 1;
  repeated Item items = 2;
}
 
message Item {
	string id = 1;
	string name = 2;
	string description = 3;
}

Nell’esempio sopra, la query sulla banca dati utilizza speciali “librerie wrapper” del framework gRPC che mettono a di­spo­si­zio­ne procedure di tra­du­zio­ne rilevanti pre-pro­gram­ma­te, importate all’inizio della procedura. Nelle ar­chi­tet­tu­re client-server di tipo diverso e in cui si uti­liz­za­no linguaggi dif­fe­ren­ti, queste procedure fanno sì che in­ter­fac­ce al­tri­men­ti in­com­pa­ti­bi­li possano co­mu­ni­ca­re le une con le altre. Ad esempio, vengono generate le classi ne­ces­sa­rie per la lettura e la scrittura dei messaggi.

La figura seguente mostra come la de­fi­ni­zio­ne dei servizi (inventory.proto) regola la query su una banca dati in un’ar­chi­tet­tu­ra client-server:

HTTP/2: streaming con pre­sta­zio­ni ot­ti­miz­za­te

In gRPC, il pro­to­col­lo HTTP/2 riveste un ruolo fon­da­men­ta­le in quanto permette il tra­sfe­ri­men­to di dati binari compatti e rende par­ti­co­lar­men­te ef­fi­cien­te lo scambio di messaggi e dati. Il pro­to­col­lo di rete mette a di­spo­si­zio­ne quattro varianti di Remote Procedure Calls:

1. le RPC unarie sono il modello gRPC più semplice. Con queste RPC, il client invia al server un’unica richiesta. Come avviene in una normale chiamata a una funzione, riceve quindi un’unica risposta.

Esempio: rpc SayHello (Hel­lo­Re­que­st) re­sti­tui­sce risposta (Hel­lo­Re­spon­se)

2. Con le RPC di streaming del server può essere rea­liz­za­to uno scambio di messaggi più complesso all’interno di una singola chiamata RPC. Per prima cosa, il client invia una richiesta al server. Suc­ces­si­va­men­te riceve come risposta dal server uno stream con­te­nen­te una sequenza di messaggi più ar­ti­co­la­ta (com­pi­la­zio­ne di messaggi ef­fi­cien­te all’interno di una singola chiamata RPC). Il client continua la lettura dello stream fino a che non ci sono più messaggi.

Esempio: rpc Lo­tsO­fRe­plies (Hel­lo­Re­que­st) re­sti­tui­sce (stream Hel­lo­Re­spon­se)

3. Con le RPC di streaming del client il processo è invertito: il client scrive una sequenza di messaggi e la invia tramite stream al server. Dopo avere com­ple­ta­to i messaggi, il client attende che il server li legga e fornisca la risposta. Anche in questo caso, la com­pi­la­zio­ne dei messaggi avviene all’interno di una singola chiamata RPC.

Esempio: rpc Lo­tsOf­Gree­tings (stream Hel­lo­Re­que­st) re­sti­tui­sce (Hel­lo­Re­spon­se)

4. Le RPC di streaming bi­di­re­zio­na­le sono la forma di co­mu­ni­ca­zio­ne più complessa, in cui entrambi i lati inviano una sequenza di messaggi. I due stream di dati lavorano in modo in­di­pen­den­te l’uno dall’altro, così che client e server possono leggere e scrivere in qualunque sequenza: ad esempio il server può attendere che tutti i messaggi siano arrivati prima di scrivere la sua risposta. Può tuttavia anche leggere un messaggio alla volta e scrivere la risposta cor­ri­spon­den­te. È inoltre possibile un’altra com­bi­na­zio­ne dei processi di lettura e scrittura.

Esempio: rpc BidiHello (stream Hel­lo­Re­que­st) re­sti­tui­sce (stream Hel­lo­Re­spon­se)

Le varianti da 2 a 4 sta­bi­li­sco­no, con richieste ni­di­fi­ca­te, un mul­ti­ple­xing par­ti­co­lar­men­te ef­fi­cien­te in cui, all’interno di un’unica con­nes­sio­ne TCP, vengono riuniti più segnali che possono essere trasmessi si­mul­ta­nea­men­te tramite la rete. I blocchi nel traffico dati vengono superati grazie al potente pro­to­col­lo HTTP/2.

Vantaggi e svantaggi di gRPC

gRPC offre numerosi vantaggi: si tratta di una tec­no­lo­gia re­la­ti­va­men­te semplice da im­ple­men­ta­re, poiché crea i file .proto uti­liz­zan­do un IDL facile che può essere appreso in tempi re­la­ti­va­men­te rapidi. L’utente può quindi ampliare con facilità i programmi creati au­to­no­ma­men­te con una potente in­ter­fac­cia gRPC e tra­sfe­ri­re anche file di grandi di­men­sio­ni con una velocità molto più elevata.

Inoltre, gRPC è am­pia­men­te testato e altamente scalabile, ed è quindi uti­liz­za­bi­le anche per co­mu­ni­ca­zio­ni più complesse e di maggiore portata, ad esempio nelle ar­chi­tet­tu­re client-server collegate in rete a livello mondiale. Il pro­to­col­lo HTTP/2, inoltre, aumenta l’ef­fi­cien­za non solo at­tra­ver­so il mul­ti­ple­xing e lo streaming bi­di­re­zio­na­le: sono infatti possibili anche com­pres­sio­ni degli header che riducono in misura si­gni­fi­ca­ti­va il volume dei dati delle richieste e delle risposte all’interno della rete.

La struttura stra­ti­fi­ca­ta e for­te­men­te stan­dar­diz­za­ta del framework gRPC riduce inoltre il lavoro ne­ces­sa­rio per la pro­gram­ma­zio­ne. Gli svi­lup­pa­to­ri possono così con­cen­trar­si in modo prio­ri­ta­rio sull’im­ple­men­ta­zio­ne dei metodi. Se sono ne­ces­sa­rie modifiche, i pro­gram­ma­to­ri e gli svi­lup­pa­to­ri di sistema be­ne­fi­cia­no della pos­si­bi­li­tà di accedere li­be­ra­men­te ai codici sorgente.

I buffer di pro­to­col­lo e i relativi com­pi­la­to­ri protobuf per­met­to­no inoltre una co­mu­ni­ca­zio­ne il­li­mi­ta­ta: sistemi operativi diversi, com­po­nen­ti dif­fe­ren­ti di ar­chi­tet­tu­re client-server e linguaggi di pro­gram­ma­zio­ne diversi non rap­pre­sen­ta­no più un ostacolo. Così, un software scritto in C può co­mu­ni­ca­re ad esempio con un software Java. I com­pi­la­to­ri protobuf sono oggi di­spo­ni­bi­li per molti altri linguaggi, ad esempio per C#, C++, Go, Objective-C, Java, Python, Node.js, Android Java, Swift, Ruby e PHP.

Un altro vantaggio di gRPC è co­sti­tui­to dalla sua fles­si­bi­li­tà. Il sistema può essere uti­liz­za­to ad esempio sia per lo scambio di dati di mi­cro­ser­vi­zi, sia per app mobili che con­di­vi­do­no i propri dati con dei server. Un altro punto a favore di gRPC è il fatto che il pro­to­col­lo permette l’im­ple­men­ta­zio­ne delle odierne tec­no­lo­gie di sicurezza. gRPC dispone di un’au­ten­ti­ca­zio­ne integrata e richiede l’utilizzo di SSL/TLS per l’au­ten­ti­ca­zio­ne e la crit­to­gra­fia dello scambio.

Tra i punti deboli di gRPC ri­cor­dia­mo i seguenti: in base allo stato attuale della tecnica, i test delle in­ter­fac­ce gRPC sono passibili di mi­glio­ra­men­to. I messaggi gRPC co­di­fi­ca­ti con protobuf non sono leggibili dagli esseri umani. Di con­se­guen­za, l’analisi del traffico dati e, in par­ti­co­la­re, la ricerca e la ri­so­lu­zio­ne degli errori (debug) ri­chie­do­no l’utilizzo di ulteriori istanze per trasporre il codice in una forma com­pren­si­bi­le e lo­ca­liz­za­re così le origini degli errori. Altri svantaggi derivano dal col­le­ga­men­to in rete di ar­chi­tet­tu­re client-server di­stri­bui­te. gRPC collega computer distanti tra loro e risulta pertanto più vul­ne­ra­bi­le rispetto ai sistemi locali. La sua ef­fi­cien­za dipende dalla di­spo­ni­bi­li­tà di una rete stabile e potente; inoltre, la rete, il traffico dati, i pro­to­col­li di tra­smis­sio­ne nonché client e server devono essere sicuri da po­ten­zia­li attacchi di hacker. Un ulteriore svan­tag­gio è rap­pre­sen­ta­to dal fatto che gRPC non supporta il mul­ti­ca­sting.

gRPC e REST a confronto

Grazie alle sue ca­rat­te­ri­sti­che positive, gRPC rap­pre­sen­ta un’al­ter­na­ti­va con­cor­ren­zia­le a REST (Re­pre­sen­ta­tio­nal State Transfer). Quest’ultimo è adatto in par­ti­co­la­re per servizi semplici, mentre gRPC mostra i suoi punti di forza con in­ter­fac­ce (API) e servizi più complessi. Per lo scambio di dati tra ap­pli­ca­zio­ni, REST utilizza ge­ne­ral­men­te il formato JSON, che è basato su file di testo e grava quindi pe­san­te­men­te sulle risorse di rete.

Per contro, grazie ai buffer di pro­to­col­lo e a HTTP/2, gRPC può or­ga­niz­za­re un flusso di dati molto più compatto. Grazie alla se­ria­liz­za­zio­ne e alla bi­na­riz­za­zio­ne dei dati, lo spazio di memoria ne­ces­sa­rio risulta pertanto ridotto quasi del 70 percento rispetto ad esempio a JSON. Inoltre lo streaming bi­di­re­zio­na­le, che funziona senza blocchi per lo scambio dei dati, ga­ran­ti­sce rispetto a REST si­gni­fi­ca­ti­vi vantaggi in termini di pre­sta­zio­ni e velocità.

At­tual­men­te la col­la­bo­ra­zio­ne con le web app è ancora mi­glio­ra­bi­le, poiché spesso queste ultime non sono ot­ti­miz­za­te per l’utilizzo di buffer di pro­to­col­lo, per l’“approccio in funzione del contratto”, tipico di gRPC, nonché per le API contract first del framework gRPC. Pe­na­liz­zan­te per la col­la­bo­ra­zio­ne con le ap­pli­ca­zio­ni web è il fatto che nessun servizio gRPC può ancora essere ri­chia­ma­to di­ret­ta­men­te da un browser.

Nel caso di REST questo problema non sussiste poiché, con­tra­ria­men­te al più recente HTTP/2, il classico pro­to­col­lo HTTP è sup­por­ta­to da tutti i browser. Tuttavia, questa lacuna può essere colmata con uno sforzo ac­cet­ta­bi­le, così che lo stesso servizio può essere uti­liz­za­to per un’ap­pli­ca­zio­ne web e per un’app mobile. Una pos­si­bi­li­tà al riguardo è rap­pre­sen­ta­ta da gRPC-Web. Gli svi­lup­pa­to­ri di gRPC stanno lavorando a ulteriori soluzioni per sem­pli­fi­ca­re il più possibile la col­la­bo­ra­zio­ne tra gRPC e i tool basati sul web.

Dove viene uti­liz­za­to gRPC?

gRPC è par­ti­co­lar­men­te indicato per rea­liz­za­re una co­mu­ni­ca­zio­ne in­ter­pro­ces­so ef­fi­cien­te nelle ar­chi­tet­tu­re client-server di­stri­bui­te in cui risultano im­por­tan­ti una bassa latenza e un elevato volume di dati e messaggi. All’interno dei centri di calcolo e fra centri di calcolo distanti gli uni dagli altri, gRPC viene spesso uti­liz­za­to per collegare servizi o mi­cro­ser­vi­zi. Poiché i tool gRPC sup­por­ta­no la maggior parte dei più comuni linguaggi di sviluppo sono spesso uti­liz­za­ti in ambienti mul­ti­lin­gue.

La velocità, l’ef­fi­cien­za e il plu­ri­lin­gui­smo depongono a favore dell’utilizzo di gRPC in ambito mobile e nella co­mu­ni­ca­zio­ne delle app. gRPC regola sempre più l’ultimo miglio dell’ela­bo­ra­zio­ne dati di­stri­bui­ta, col­le­gan­do di­spo­si­ti­vi, ap­pli­ca­zio­ni mobili e browser con servizi backend.

Il potente streaming tramite HTTP/2 fa di gRPC il sistema pre­de­sti­na­to per la co­mu­ni­ca­zio­ne punto a punto in tempo reale. L’Internet of things (tec­no­lo­gie smart home) trae vantaggio dal pro­ce­di­men­to a basso consumo di risorse, in quanto regola sempre più la co­mu­ni­ca­zio­ne di low resource client. In ragione dei vantaggi in termini di pre­sta­zio­ni e della sem­pli­ci­tà di sviluppo, in futuro questa tec­no­lo­gia di co­mu­ni­ca­zio­ne potrebbe con­qui­sta­re un ruolo di primo piano nel cloud, limitando l’attuale pre­do­mi­nan­za di REST. gRPC viene at­tual­men­te con­si­de­ra­to anche un’al­ter­na­ti­va a XML (Ex­ten­si­ble Markup Language).

N.B.

XML è un formato fre­quen­te­men­te uti­liz­za­to per lo scambio di dati e la me­mo­riz­za­zio­ne strut­tu­ra­ta di in­for­ma­zio­ni.

Vai al menu prin­ci­pa­le