Ottimizzazione TCP per le prestazioni di rete

Questa pagina illustra i metodi per calcolare le impostazioni corrette per diminuire la latenza delle connessioni TCP in Google Cloud e in scenari ibridi. Questa pagina ti aiuta anche a capire come migliorare la latenza di connessione tra i processi in Google Cloud.

L'architettura moderna dei microservizi consiglia agli sviluppatori di creare piccoli servizi con un'unica responsabilità. I servizi dovrebbero comunicare tramite TCP o UDP, in base alle aspettative di affidabilità del sistema. È quindi fondamentale che i sistemi basati su microservizi comunichino con affidabilità e bassa latenza.

Google Cloud offre affidabilità e bassa latenza fornendo una rete globale, il che significa che gli utenti delle tue applicazioni possono anche espandersi a livello globale. Avere una rete globale significa creare una rete Virtual Private Cloud (VPC) che comprende regioni e zone. Le applicazioni possono connettersi tra loro in regioni e zone senza mai uscire dalla rete Google Cloud.

Le applicazioni scritte per un ambiente data center tradizionale possono presentare prestazioni lente quando vengono spostate in un ambiente cloud ibrido, ovvero quando alcuni componenti dell'applicazione vengono eseguiti in un data center aziendale e altri vengono eseguiti nel cloud. Le prestazioni lente possono essere dovute a una serie di fattori. Questo articolo si concentra sulle latenze di round trip e su come la latenza influisca sulle prestazioni TCP nelle applicazioni che trasferiscono una notevole quantità di dati su qualsiasi parte della rete.

Il problema: latenza e comportamento TCP

TCP utilizza un meccanismo di windowing per impedire a un mittente veloce di eseguire in eccesso un ricevitore lento. Il destinatario pubblicizza la quantità di dati che deve inviare prima che quest'ultimo debba attendere un aggiornamento della finestra dal destinatario. Di conseguenza, se un'applicazione ricevente non può ricevere dati sulla connessione, esiste un limite alla quantità di dati che possono essere messi in coda in attesa dell'applicazione.

La finestra TCP consente un uso efficiente della memoria sui sistemi di invio e ricezione. Quando l'applicazione ricevente consuma dati, gli aggiornamenti delle finestre vengono inviati al mittente. L'aggiornamento più rapido della finestra avviene con un round trip, che porta alla seguente formula per uno dei limiti alle prestazioni di trasferimento collettivo di una connessione TCP:

Velocità effettiva <= dimensione finestra / latenza tempo di round trip (RTT)

Nella progettazione originale per TCP, questa finestra ha una dimensione massima di 65.535 byte (64 KiB - 1). Si tratta della quantità massima di dati che il mittente poteva inviare prima che ricevesse un aggiornamento della finestra per consentire l'invio di altri dati.

Modifiche in TCP dalla sua introduzione

Da quando è stato introdotto il protocollo TCP, alcune funzionalità chiave sono cambiate:

  • Le velocità di rete tipiche sono aumentate di quattro ordini di grandezza.
  • La memoria tipica di un sistema è aumentata di quattro ordini di grandezza.

Il risultato della prima modifica è che le dimensioni delle finestre TCP originali hanno portato a un uso inefficiente delle risorse di rete. Un mittente inviava l'equivalente di una finestra di dati alla migliore velocità possibile in base alle condizioni della rete, quindi rimane inattivo per un lungo periodo di tempo mentre attende l'aggiornamento della finestra TCP. Il risultato della seconda modifica è che mittenti e destinatari possono utilizzare più memoria per il networking in modo da risolvere il limite esposto dalla prima modifica.

Il seguente diagramma illustra questo interscambio.

Il mittente invia solo 64.000 di dati e trascorre molto tempo dopo l'invio prima di ricevere un aggiornamento della finestra

Il mittente non può utilizzare appieno la rete perché è in attesa dell'aggiornamento della finestra TCP prima di inviare dati aggiuntivi.

Invio di più dati alla volta

La soluzione consiste nell'inviare più dati alla volta. All'aumentare della larghezza di banda della rete, è possibile inserire una quantità maggiore di dati nel tubo (rete) e all'aumentare della lunghezza del tubo, è necessario più tempo per confermare la ricezione dei dati. Questa relazione è nota come prodotto con ritardo della larghezza di banda (BDP). Questo valore viene calcolato moltiplicando la larghezza di banda per il tempo di round trip (RTT), ottenendo un valore che specifica il numero ottimale di bit da inviare per riempire il tubo. La formula è questa:

BDP (bit) = larghezza di banda (bit/secondo) * RTT (secondi)

Il BDP calcolato viene utilizzato come dimensione della finestra TCP per l'ottimizzazione.

Ad esempio, immagina di avere una rete da 10 Gbps con un RTT di 30 millisecondi. Per le dimensioni della finestra, utilizza il valore delle dimensioni originali della finestra TCP (65535 byte). Questo valore non si avvicina a sfruttare la funzionalità della larghezza di banda. Le massime prestazioni TCP possibili su questo collegamento sono le seguenti:

(65535 byte * 8 bit/byte) = larghezza di banda * 0,030 secondi
larghezza di banda = (65535 byte * 8 bit/byte) / 0,030 secondi
larghezza di banda = 524280 bit / 0,030 secondi
larghezza di banda = 1747 / 000 bit

In altre parole, questi valori generano una velocità effettiva di poco superiore a 17 Mbit al secondo, una piccola parte della capacità di rete di 10 Gbps.

Soluzione: scalabilità TCP a livello di finestra

Per risolvere i limiti delle prestazioni imposti dal design originale delle dimensioni della finestra TCP, sono state introdotte estensioni al protocollo TCP che consentono di scalare la dimensione della finestra a valori molto più grandi. La scalabilità delle finestre supporta finestre fino a 1.073.725.440 byte, o quasi 1 GiB. Questa funzionalità è descritta in RFC 7323 come opzione di scalabilità delle finestre TCP.

Le estensioni di scalabilità delle finestre espandono la definizione della finestra TCP in modo che utilizzi 30 bit, quindi usano un fattore di scala implicito per inserire questo valore a 30 bit nel campo della finestra a 16 bit dell'intestazione TCP. Per vedere se la funzionalità è abilitata su sistemi basati su Linux, utilizza il seguente comando:

sudo sysctl net.ipv4.tcp_window_scaling

Tutte le macchine virtuali Google Cloud Linux hanno questa funzionalità abilitata per impostazione predefinita. Se viene restituito un valore 1, significa che l'opzione è abilitata. Se la funzionalità è disabilitata, puoi abilitarla utilizzando il seguente comando:

sudo sysctl -w net.ipv4.tcp_window_scaling=1

Velocità effettiva con una finestra di dimensioni maggiori

Puoi utilizzare l'esempio precedente per mostrare il vantaggio della scalabilità delle finestre. Come prima, supponiamo una rete di 10 Gbps con una latenza di 30 millisecondi, quindi calcola una nuova dimensione di finestra utilizzando questa formula:

(Velocità del link * latenza) / 8 bit = dimensione della finestra

Se inserisci i numeri di esempio, ottieni questo:

(10 Gbps * 30 ms/1000 sec) / 8 bit/byte = dimensione finestra
(10.000 Mbps * 0,030 secondi) / 8 bit/byte = 37,5 MB

Aumentando le dimensioni della finestra TCP a 37 MB è possibile aumentare il limite teorico delle prestazioni per i trasferimenti collettivi TCP fino a un valore simile alla capacità di rete. Ovviamente, molti altri fattori possono limitare le prestazioni, tra cui l'overhead del sistema, la dimensione media dei pacchetti e il numero di altri flussi che condividono il collegamento. Tuttavia, come puoi vedere, le dimensioni delle finestre attenuano sostanzialmente i limiti imposti dalle precedenti dimensioni limitate delle finestre.

Impostazione degli aggiustamenti di Linux per modificare le dimensioni della finestra TCP

In Linux, le dimensioni della finestra TCP sono influenzate dai seguenti regolabili sysctl(8):

net.core.rmem_max
net.core.wmem_max
net.ipv4.tcp_rmem
net.ipv4.tcp_wmem

I primi due regolabili influiscono sulla dimensione massima della finestra TCP per le applicazioni che tentano di controllare direttamente la dimensione della finestra TCP, limitando la richiesta delle applicazioni a un massimo di quei valori. Le seconda due impostazioni regolabili influiscono sulla dimensione della finestra TCP per le applicazioni che lasciano l'ottimizzazione automatica di Linux.

Il valore ottimale della dimensione della finestra dipende dalle circostanze specifiche, ma un punto di partenza è il maggiore BDP (prodotto con ritardo di larghezza di banda) per il percorso o i percorsi su cui prevedi che il sistema invii dati. In tal caso, vuoi impostare le regolazioni seguendo questi passaggi:

  1. Assicurati di disporre dei privilegi root.
  2. Ottieni le impostazioni correnti del buffer. Salva le impostazioni nel caso in cui vuoi ripristinarle.

    sudo sysctl -a | grep mem
    
  3. Imposta una variabile di ambiente sulla nuova dimensione della finestra TCP che vuoi utilizzare:

    MaxExpectedPathBDP=8388608
    
  4. Imposta la dimensione massima del buffer di ricezione del sistema operativo per tutti i tipi di connessioni:

    sudo sysctl -w net.core.rmem_max=$MaxExpectedPathBDP
    
  5. Imposta la dimensione massima del buffer di invio del sistema operativo per tutti i tipi di connessioni:

    sudo sysctl -w net.core.wmem_max=$MaxExpectedPathBDP
    
  6. Configura le impostazioni del buffer di memoria di ricezione TCP (tcp_rmem):

    sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 $MaxExpectedPathBDP"
    

    L'impostazione tcp_rmem richiede tre valori:

    • La dimensione minima del buffer di ricezione che può essere allocata per un socket TCP. In questo esempio, il valore è di 4096 byte.
    • La dimensione predefinita del buffer di ricezione, che sostituisce anche il valore /proc/sys/net/core/rmem_default utilizzato da altri protocolli. Nell'esempio, il valore è di 87380 byte.
    • La dimensione massima del buffer di ricezione che può essere allocata per un socket TCP. Nell'esempio, è impostato sul valore che hai impostato in precedenza (8388608 byte).
  7. Configura le impostazioni del buffer di memoria di invio TCP (tcp_wmem):

    sudo sysctl -w net.ipv4.tcp_wmem="4096 16384 $MaxExpectedPathBDP"
    

    L'impostazione tcp_wmem richiede tre valori:

    • Lo spazio minimo di buffer di invio TCP disponibile per un singolo socket TCP.
    • Lo spazio buffer predefinito consentito per un singolo socket TCP.
    • Lo spazio di buffer di invio TCP massimo.
  8. Imposta gli aggiustamenti in modo che le connessioni successive utilizzino i valori che hai specificato:

    sudo sysctl -w net.ipv4.route.flush=1
    

Per mantenere queste impostazioni tra i riavvii, aggiungi i comandi che hai impostato in precedenza al file /etc/sysctl.conf:

sudo bash -c 'cat << EOF >> /etc/sysctl.conf
net.core.rmem_max=8388608
net.core.wmem_max=8388608
net.ipv4.tcp_rmem=4096 87380 8388608
net.ipv4.tcp_wmem=4096 16384 8388608
net.ipv4.route.flush=1
EOF'

Test di RTT con una dimensione della finestra aggiornata

Quando TCP ha una finestra di dimensioni sufficienti per utilizzare il BDP, l'immagine cambia, come mostrato nel seguente diagramma:

Il mittente invia una grande quantità di dati alla volta e impiega pochissimo tempo ad attendere l'aggiornamento della finestra

Le dimensioni della finestra TCP possono essere sempre adattate in base alle risorse disponibili per il processo coinvolto e all'algoritmo TCP in uso. Come mostra il diagramma, la scalabilità delle finestre consente a una connessione di superare di gran lunga la dimensione della finestra di 65 KiB definita nella specifica TCP originale.

Puoi verificarlo autonomamente. In primo luogo, assicurati di aver modificato le dimensioni delle finestre TCP sul computer locale e su un computer remoto impostando gli eventi sintonizzabili su entrambe le macchine. Quindi esegui questi comandi:

dd if=/dev/urandom of=sample.txt bs=1M count=1024 iflag=fullblock
scp sample.txt your_username@remotehost.com:/some/remote/directory

Il primo comando crea un file sample.txt da 1 GB contenente dati casuali. Il secondo comando copia il file dalla tua macchina locale a una macchina remota.

Osserva l'output comando scp sulla console, che mostra la larghezza di banda in Kbps. Dovresti notare una notevole differenza nei risultati prima e dopo le modifiche alle dimensioni della finestra TCP.

Passaggi successivi