REST o GraphQL: oltre 3.000 richieste il vantaggio può capovolgersi

|Autore: Redazione QUASA|6 min di lettura
REST o GraphQL: oltre 3.000 richieste il vantaggio può capovolgersi

Nel confronto sperimentale su tre applicazioni, GraphQL migliora il tempo per richiesta concorrente in due casi, ma nella prova Tech Teams con 3.000 richieste e concorrenza pari a uno REST registra 300,65 ms contro 517,20 ms per GraphQL. Le prove si fermano a quel carico: il risultato mostra che il vantaggio può invertirsi, senza fissare una soglia valida per ogni API.

Per scegliere tra REST e GraphQL bisogna distinguere il tempo percepito dal client dal lavoro svolto dal server. GraphQL è interessante quando i client chiedono combinazioni variabili di campi e relazioni; REST può risultare più conveniente con risposte stabili, letture ripetute e una cache HTTP efficace. La latenza sotto carico e il tempo necessario a scrivere le query sono altre due misure, da valutare separatamente.

Campi richiesti e viaggi sulla rete

Confronto schematico tra campi selezionati con GraphQL e rappresentazione di una risorsa REST.

GraphQL lascia al client la scelta dei campi da ricevere. Se una schermata usa soltanto una piccola parte di una risorsa ampia, questa selezione può alleggerire la risposta; se servono dati collegati che gli endpoint REST espongono separatamente, può evitare chiamate successive. Il beneficio dipende dalla forma della richiesta e dal tempo di andata e ritorno sulla rete, non dal solo numero di endpoint disponibili.

Anche un’API REST può offrire rappresentazioni mirate: un endpoint dedicato o parametri per scegliere i campi possono ridurre i dati superflui. Viceversa, una singola richiesta GraphQL può attraversare molte relazioni e restituire una risposta estesa. Contare soltanto le chiamate HTTP rischia quindi di nascondere sia i byte trasferiti sia il lavoro necessario a costruire la risposta.

Un confronto sensato parte dallo stesso compito del client. Per quel compito contano la dimensione effettiva delle risposte, l’eventuale compressione e il tempo della sequenza completa di chiamate. Le richieste REST indipendenti possono procedere in parallelo; quelle che dipendono dal risultato precedente richiedono invece più viaggi consecutivi. In quest’ultimo caso la flessibilità di GraphQL ha maggiori possibilità di incidere sulla latenza visibile all’utente.

Il costo della query quando cresce il carico

Una risposta più piccola non garantisce un’esecuzione più rapida. In GraphQL ogni campo richiesto deve essere risolto: una relazione annidata può attivare letture ripetute dal database o da un servizio a valle. La guida ufficiale alle prestazioni di GraphQL descrive il problema N+1 e indica il raggruppamento delle letture, la paginazione e i limiti alla complessità delle operazioni tra le misure per contenerlo.

Questo spiega perché il risultato di un test appartiene alle implementazioni confrontate, non allo stile API preso isolatamente. Un resolver che interroga il database per ogni oggetto può consumare il tempo risparmiato sulla rete. Un endpoint REST che ricostruisce più volte gli stessi dati può avere il problema opposto. Anche la concorrenza modifica il quadro: molte richieste in sequenza esercitano il server in modo diverso da richieste simultanee.

Per localizzare il costo servono misure distinte: tempo totale visto dal client, tempo impiegato dall’API, interrogazioni al database, capacità di servire richieste ed errori. Se aumenta soltanto il tempo dell’API, ridurre i byte della risposta può cambiare poco. Se il server risponde rapidamente ma il client attende più chiamate dipendenti, intervenire sulla forma della richiesta può avere un effetto maggiore.

La cache può cambiare l’esito

Confronto tra cache HTTP di una risorsa REST e cache di una query GraphQL persistente.

Quando molti client ripetono la stessa lettura, la cache può pesare più della differenza tra due risposte generate dal server. Una risorsa REST identificata da un URL può sfruttare la cache HTTP se le intestazioni e le regole di accesso lo permettono. Se la risposta arriva dalla cache, il server applicativo evita di ricostruirla: confrontare quel percorso con una query che raggiunge sempre i resolver mescolerebbe condizioni diverse.

GraphQL dispone a sua volta di più possibilità. Le query inviate con GET possono beneficiare della cache HTTP o di una CDN quando la risposta porta intestazioni adeguate; le query persistenti permettono di inviare un identificatore al posto del documento completo. Per la cache degli oggetti sul client, la documentazione GraphQL sulla cache raccomanda identificatori univoci, così che lo stesso oggetto possa essere riconosciuto in risposte diverse.

La variabile decisiva è quante richieste siano davvero riutilizzabili. Combinazioni di campi sempre differenti riducono le occasioni di riuso della risposta completa; dati condivisi e letti spesso le aumentano. Le risposte personalizzate richiedono inoltre chiavi e regole di accesso coerenti con l’utente autorizzato, qualunque sia lo stile API. Per interpretare una prova di latenza occorre quindi sapere quante risposte sono state servite dalla cache e quali hanno raggiunto l’origine.

Scrivere una query costa tempo; gestire l’API è un altro lavoro

Nell’esperimento sulle query della API di GitHub, la mediana è di 6 minuti per GraphQL e 9 per REST.

Il tempo di sviluppo non segue necessariamente la latenza del servizio. In un esperimento controllato su query per la API di GitHub, 22 studenti hanno lavorato su otto compiti: la mediana del tempo per implementare una query è stata di 6 minuti con GraphQL e 9 con REST. Il vantaggio è risultato maggiore per le query REST con endpoint e parametri più complessi.

Il risultato riguarda chi scrive le richieste del client. Uno schema tipizzato e gli strumenti di completamento possono rendere più agevole individuare campi e costruire query articolate; lo studio non misura però il tempo necessario a progettare, proteggere e mantenere un intero servizio. Sul lato server, GraphQL richiede di definire lo schema, risolvere i campi, applicare l’autorizzazione e controllare il costo delle operazioni ammesse.

Se molte applicazioni chiedono selezioni diverse degli stessi dati, il tempo risparmiato dai client può giustificare quel lavoro. Se le operazioni sono poche e stabili, endpoint REST già adatti allo scopo possono richiedere meno interventi complessivi. La produttività di chi sviluppa le query e il costo di gestione dell’API vanno perciò tenuti in colonne separate: migliorare la prima misura non implica automaticamente ridurre la seconda.

Quale scelta regge nel proprio scenario

GraphQL ha più valore quando i client cambiano spesso le proprie esigenze, attraversano molte relazioni e pagano il costo di chiamate dipendenti. In questo scenario contano la selezione dei campi e la facilità di comporre le query, purché resolver, accessi al database e complessità delle operazioni siano sotto controllo. REST è spesso conveniente quando le rappresentazioni sono prevedibili, gli endpoint coprono già i compiti principali e le letture ripetute sfruttano bene la cache.

La decisione emerge confrontando, per gli stessi compiti, byte e viaggi di rete, latenza al carico previsto, riuso della cache e lavoro richiesto a client e server. Queste misure possono indicare vincitori diversi. Il caso Tech Teams rende concreta questa possibilità: una scelta favorevole in alcune condizioni può perdere il vantaggio quando cambia il carico dell’implementazione esaminata.

Leggi anche:

Condividi:

Iscriviti alla nostra newsletter

Ricevi le ultime notizie su Web3, IA e cripto direttamente nella tua casella di posta.

0