Probabilmente avete letto che HTTPS apre una nuova connessione TCP e un nuovo handshake TLS per ogni richiesta API, così un tunnel che resta attivo per un’ora sembra più economico. La prima metà di questa affermazione è di solito falsa. Un client supportato riutilizza una connessione già stabilita per molti scambi, e un benchmark che crea un nuovo client a ogni chiamata misura il ciclo di vita anziché la protezione. Il resto di questa pagina spiega cosa misurare invece.

Che cosa richiede davvero il riutilizzo

La persistenza fa parte del modello HTTP e non è un trucco: una connessione trasporta più scambi di richiesta e risposta. La connessione termina quando una delle due parti la chiude, quando il server ritira una connessione inattiva o sovraccarica, o quando un’intestazione o una regola del protocollo indica che la connessione non può essere riutilizzata. HTTPS colloca quella conversazione dentro TLS senza richiedere un nuovo handshake per ogni scambio. Quindi una seconda richiesta non ripete l’handshake della prima, a meno che qualcosa abbia chiuso la connessione nel frattempo.

Il riutilizzo ha anche una condizione che le applicazioni rompono facilmente. Un client che intende riutilizzare una connessione deve leggere l’intero corpo della risposta, e una risposta abbandonata a metà è il modo abituale con cui un pool di connessioni sparisce senza che nessuno se ne accorga.

Controllate il client supportato e il ciclo di vita del pool di connessioni della libreria invece di dare per scontato che il pooling sia attivo o disattivo. Annotate anche la versione HTTP negoziata, perché HTTP/2 e HTTP/3 gestiscono il riutilizzo delle connessioni in modo diverso da HTTP/1.1. Trattate la versione negoziata come parte della misurazione, non come nota a piè di pagina.

Perché il confronto misura il ciclo di vita

Creare un client nuovo per ogni operazione e confrontarlo con un tunnel connesso da un’ora confronta la configurazione della connessione con lo stato stazionario. È un benchmark legittimo, e non è HTTPS contro VPN. Due esecuzioni con la stessa configurazione di client descrivono meglio il comportamento di una sola, soprattutto quando la prima esecuzione scalda un resolver o una cache di connessioni.

Mantenete costanti l’operazione API, il server, l’account e i dati, altrimenti il confronto porta più di una variabile. Decidete in anticipo dove collocate il cronometro, perché configurazione, negoziazione TLS, esecuzione dell’applicazione e consegna della risposta contribuiscono diversamente al totale. Un solo cronometro della prima richiesta caratterizza la configurazione e non dice nulla sul traffico stazionario che eseguite davvero. Annotate i limiti del cronometro accanto ai numeri.

Separare la configurazione a freddo dalle richieste calde

Misurate la prima richiesta separatamente da quelle che seguono. Poi aggiungete ciò che il servizio vede davvero: periodi di inattività, picchi, concorrenza, dimensione della risposta e riconnessioni.

Lasciate attivi la validazione dei certificati e HTTPS su entrambi i percorsi, perché rimuoverli misura un progetto di sicurezza diverso e non più veloce. Se il tunnel cambia la rotta o la posizione del gateway, segnalate quella differenza separatamente invece di attribuire ogni variazione di tempo alla cifratura, poiché percorso, perdita e coda possono dominare una richiesta piccola. Eseguite ogni percorso due volte sulla stessa rotta prima di trarre una conclusione. Annotate il protocollo negoziato e i limiti del cronometro con entrambe le esecuzioni.

Prevedere la connessione che si chiude

Persistente non significa permanente. Un server, un proxy o un cambio di rete possono chiudere una connessione durante un periodo di inattività, e il client deve recuperare con il comportamento supportato dalla sua libreria. Quel recupero ha una macchina a stati: la richiesta può essersi completata sul server, oppure può essere fallita prima che il server la leggesse, e un socket chiuso non dice al chiamante quale delle due cose è accaduta. Un’operazione non idempotente in quella posizione non può essere semplicemente ripetuta, perché una ripetizione trasforma un esito sconosciuto in una scrittura duplicata. È qui che un tunnel caldo e una connessione calda si comportano allo stesso modo, poiché entrambi possono fallire nel momento in cui il lavoro è in corso.

Usate il meccanismo documentato di nuovo tentativo o di idempotenza del servizio invece di un ciclo che riapre il socket. Provate il recupero in modo esplicito: chiudete una connessione inattiva e osservate cosa fa il client dopo. Riaprire un socket non rende sicura la ripetizione di una chiamata che modifica lo stato.

Scegliere prima il confine, poi regolare

Scegliete il confine di rete dai requisiti di accesso e fiducia prima di ottimizzare qualsiasi cosa. Una VPN protegge il segmento tra i suoi peer, mentre gli endpoint dell’applicazione e qualsiasi segmento in chiaro fuori dal tunnel contano ancora. Poi regolate il ciclo di vita della connessione dentro quel confine. La conclusione del tunnel meno costoso deriva solo dalla convinzione che ogni richiesta ripeta l’handshake, e quella convinzione è ciò che viene messo alla prova qui.

La sezione di RFC 9112 sulla persistenza è il riferimento per ciò che il riutilizzo promette davvero, comprese le condizioni che terminano una connessione. Leggetela una volta prima di fidarvi di un benchmark che le ignora.

Articoli correlati