La rete globale in Google Cloud offre alta affidabilità e bassa latenza connettendo le applicazioni in regioni e zone diverse senza uscire dalla rete Google. Tuttavia, le impostazioni TCP/IP di Linux predefinite sono spesso ottimizzate per gli ambienti on-premise e possono causare colli di bottiglia delle prestazioni nel cloud.
Per ottenere le prestazioni migliori in Google Cloud, utilizza le impostazioni TCP/IP in questo documento, che sono ottimizzate in modo specifico per l'ambiente cloud.
Le impostazioni menzionate in questo documento sono state testate per l'utilizzo nell'ambienteGoogle Cloud . Le impostazioni sono principalmente per le comunicazioni interne delle istanze e non si applicano necessariamente alla comunicazione tra le istanze Compute Engine e gli indirizzi esterni.
Informazioni sul limite di velocità effettiva
Il protocollo TCP utilizza un meccanismo di "windowing" per gestire il flusso di dati tra un mittente e un destinatario. La velocità effettiva massima raggiungibile è regolata dalla seguente relazione:
Throughput <= window size / round-trip time (RTT) latency
Nella versione originale di TCP, la dimensione massima della finestra è limitata a 65535 byte (64 KiB - 1), il che spesso lascia le moderne reti ad alta velocità sottoutilizzate poiché il mittente attende gli aggiornamenti della finestra.
Script shell per ottimizzare le prestazioni TCP
Per migliorare le prestazioni, ti consigliamo le seguenti configurazioni TCP:
- Riduci MinRTO: recupera più rapidamente la perdita di pacchetti riducendo i ritardi di ritrasmissione.
- Attiva Fair Queueing: riduci al minimo la congestione e i cali dovuti a picchi di applicazioni.
- Disattiva avvio lento dopo l'inattività: riavvia alla velocità di trasferimento valida nota più recente dopo un periodo di inattività della connessione.
- Disattiva il treno di ACK TCP Cubic HyStart: ignora i segnali di congestione falsi positivi quando aumenti la velocità di trasferimento dei dati.
- Aumenta i budget di memoria dei socket: aumenta la quantità massima consentita di dati in transito per connessione.
- Abilita GRO hardware: aumenta l'efficienza dell'elaborazione di ricezione TCP/IP per flussi di grandi dimensioni combinando i dati in pacchetti più grandi e in numero inferiore.
- Aumenta l'MTU a 4082 byte: aumenta l'efficienza del trasferimento per i flussi con velocità effettiva elevata.
Puoi attivare queste impostazioni suggerite con il seguente script shell. Prima di eseguire lo script, assicurati di sostituire eth0 con l'interfaccia di rete principale per l'istanza di calcolo.
# Set DEV to your primary network interface
DEV=eth0
# 1. Reduce MinRTO
sysctl -w net.ipv4.tcp_rto_min_us=5000
# 2. Enable Fair Queueing
tc qdisc replace dev $DEV root fq
# 3. Disable slow start after idle
sysctl -w net.ipv4.tcp_slow_start_after_idle=0
# 4. Disable TCP Cubic HyStart ACK train
echo 2 > /sys/module/tcp_cubic/parameters/hystart_detect
# 5. Increase socket memory budgets
echo 4194304 > /proc/sys/net/core/rmem_max
echo 4194304 > /proc/sys/net/core/wmem_max
echo 4194304 > /proc/sys/net/ipv4/tcp_notsent_lowat
echo "4096 262144 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 262144 33554432" > /proc/sys/net/ipv4/tcp_wmem
# 6. Enable hardware GRO
ethtool -K $DEV rx-gro-hw on
Le sezioni seguenti descrivono in modo più dettagliato ciascuna delle impostazioni di configurazione suggerite.
Ridurre MinRTO
Recupera più rapidamente dalla perdita di pacchetti riducendo i ritardi di ritrasmissione.
Il timeout di ritrasmissione TCP (RTO) controlla il tempo di attesa di un mittente TCP per un segnale ACK prima di ritrasmettere. Linux inizializza il RTO a un secondo (in base alla
sezione 2.1 dell'RFC 6298), poi lo regola nel tempo in base altempo di round tripe (RTT)
più un margine di sicurezza.
Il valore RTO minimo (MinRTO) implementa un limite inferiore per questo aggiustamento. Se la stima dell'RTO è troppo bassa, possono verificarsi ritrasmissioni spurie, in cui il mittente ritrasmette i pacchetti mentre la risposta è ancora in corso.
Il valore predefinito di MinRTO è 200 ms, che è inutilmente conservativo per le moderne reti cloud. Un valore di 5 ms è stato testato a fondo all'interno di Google Cloud ed è un valore predefinito sicuro per le connessioni tra server Linux moderni all'interno di Google Cloud.
Un altro fattore sono gli ACK ritardati, in cui il peer ritarda le risposte ACK. Questo
ritardo consente di raggruppare gli ACK in più pacchetti di dati o di combinare un ACK
con un pacchetto di dati nella direzione opposta. I timer ACK ritardati si basano su
RTT, in modo simile al timer RTO.
La riduzione di MinRTO accelera la riparazione della perdita sulle connessioni RTT basse, ad esempio le connessioni all'interno di una zona o di una regione. Questo aggiustamento non influisce sul comportamento per le connessioni che registrano un RTT elevato, in quanto non modifica l'RTT stimato.
Configurazione di MinRTO
Puoi configurare MinRTO utilizzando uno dei due metodi:
Utilizzo di
sysctl(Linux 6.11 e versioni successive):Puoi configurare il valore MinRTO predefinito utilizzando un comando
sysctl:sysctl -w net.ipv4.tcp_rto_min_us=5000Utilizzo di
ip route(controllo per route o versioni di Linux precedenti alla 6.11):In alternativa, per le versioni precedenti di Linux o per il controllo per route, MinRTO può essere impostato in base al percorso:
ip route change default rto_min 5ms
L'approccio per route è preferibile negli ambienti in cui le connessioni potrebbero uscire Google Cloud o comunicare con stack TCP/IP non Linux. Questi sistemi potrebbero avere timer ACK ritardati diversi. Per un deployment pubblico su internet ampio, è consigliabile mantenere l'impostazione minRTO predefinita conservativa e applicare l'impostazione di 5 ms solo per le route all'interno di Virtual Private Cloud. Google Cloud
Abilita l'accodamento equo
Ridurre al minimo la congestione e la perdita di pacchetti causate dai picchi di traffico delle applicazioni.
A differenza delle code FIFO (First-In, First-Out) standard, Fair Queueing (FQ) distribuisce la larghezza di banda in modo equo tra i diversi flussi. Inoltre, regola il traffico consentendo a ogni connessione TCP di calcolare la velocità e il tempo di pubblicazione ottimali per ogni pacchetto. Se FQ è presente, lo stack TCP si basa su FQ per conservare i pacchetti fino al momento ottimale per la consegna. Questo pacing riduce i burst all'interno di un flusso, il che a sua volta riduce al minimo le perdite di pacchetti e le ritrasmissioni.
Per impostare FQ traffic shaper come traffic shaper del dispositivo di rete, utilizza il seguente comando tc (controllo del traffico):
tc qdisc replace dev $DEV root fq
Sulle istanze di grandi dimensioni con larghezza di banda di uscita elevata, il dispositivo di rete potrebbe avere più code di trasmissione. Per queste istanze potrebbe essere preferibile suddividere il traffic shaping tra le code di trasmissione installando il traffic shaper Multi Queue (MQ). Si tratta di un multiplexer che collega un shaper del traffico indipendente a ogni coda di trasmissione. I traffic shaper per coda riducono la contesa su blocchi e cacheline tra le CPU.
Disattiva l'avvio lento dopo l'inattività
Mantenere velocità di trasferimento elevate dopo un periodo di inattività della connessione.
Per evitare la congestione, le connessioni TCP iniziano inviando dati a una velocità bassa e poi aumentano esponenzialmente la velocità fino a quando non viene rilevata la perdita di pacchetti. Questa fase iniziale è nota come avvio lento.
Per impostazione predefinita, TCP torna alle impostazioni conservative "Slow Start" dopo un periodo di inattività. Un periodo di inattività può durare anche solo un timeout di ritrasmissione (RTO), come definito nella RFC 2581. La disabilitazione di questa funzionalità consente alla connessione di riprendere immediatamente all'ultimo tasso di trasmissione valido noto.
Se possibile, le applicazioni devono utilizzare connessioni di lunga durata anziché stabilire ripetutamente connessioni allo stesso peer. In questo modo si evita il costo di creazione della connessione e si mantengono le informazioni sulla congestione. Tuttavia, anche con le connessioni a lunga durata, dopo un periodo di inattività TCP dimentica le informazioni sulla congestione per impostazione predefinita e torna all'impostazione iniziale conservativa e alla fase "Slow Start".
Per disattivare l'avvio lento dopo l'inattività, utilizza il seguente comando:
sysctl -w net.ipv4.tcp_slow_start_after_idle=0
Disattiva il treno di ACK HyStart Cubic TCP
Aumenta rapidamente le velocità di trasferimento ignorando i segnali di congestione dei falsi positivi.
Il tasso di crescita esponenziale della fase "Avvio lento" può essere aggressivo, superando potenzialmente il tasso target ottimale. L'avvio ibrido (HyStart) è un meccanismo aggiuntivo progettato per uscire dalla fase di "avvio lento" in anticipo utilizzando due indicatori chiave di congestione:
- Ritardo del tempo di round trip (RTT): misura il ritardo di propagazione dei pacchetti attraverso la rete. Durante i periodi di congestione della rete, le code di pacchetti si accumulano nei link di colli di bottiglia. Ciò causa un aumento dell'RTT, che può segnalare la presenza di congestione.
- Spaziatura ACK: si basa su indicatori che segnalano che i pacchetti vengono ritardati in un collo di bottiglia, ma si concentra sugli ACK di risposta. Questo meccanismo presuppone che, senza congestione, gli ACK arriveranno con la stessa spaziatura dei pacchetti di dati originali. Questo pattern viene spesso chiamato treno ACK. Se gli ACK vengono ritardati oltre questo pattern previsto, significa che potrebbe essere presente congestione.
Per ottimizzare il rendimento, disattiva il rilevamento del treno di pacchetti ACK mantenendo attivo il meccanismo di ritardo RTT.
echo 2 > /sys/module/tcp_cubic/parameters/hystart_detect
Aumentare i budget di memoria dei socket
Aumenta il throughput massimo sui link con RTT elevato consentendo un maggior numero di dati in transito.
La quantità di dati in transito è una funzione della larghezza di banda e del ritardo di propagazione, denominata prodotto larghezza di banda-ritardo (BDP). Il BDP 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 la pipeline:
BDP (bits) = bandwidth (bits/second) * RTT (seconds)
Tutti i dati in transito devono rimanere memorizzati nel buffer del mittente nel caso in cui debbano essere ritrasmessi. I limiti di memoria dei socket TCP possono limitare direttamente il throughput raggiungibile determinando la quantità di dati in transito che può essere memorizzata nel buffer.
In Linux, i limiti di memoria dei socket TCP vengono configurati con le seguenti impostazioni
sysctl(8):
net.core.rmem_maxnet.core.wmem_maxnet.ipv4.tcp_rmemnet.ipv4.tcp_wmem
Questi limiti di memoria dei socket TCP esistono per evitare di utilizzare tutta la memoria di sistema e causare condizioni di esaurimento della memoria, soprattutto nei workload con molte connessioni. L'aumento di questi limiti può aumentare il throughput, soprattutto su percorsi RTT elevati. A meno che il conteggio delle connessioni non sia nell'ordine dei milioni, non c'è alcun rischio nell'aumentare questi limiti.
Queste variabili impostano i limiti superiori per le dimensioni del buffer del socket, non l'allocazione diretta della memoria. L'aumento di questi valori non influisce sull'allocazione effettiva della memoria per le connessioni con RTT basso, ad esempio quelle all'interno di una zona Google Cloud .
I primi due parametri configurabili influiscono sulla dimensione massima della finestra TCP per
le applicazioni che impostano direttamente la dimensione della finestra TCP, cosa che fanno relativamente poche
applicazioni. Questi limiti vincolano ciò che un'applicazione può richiedere esplicitamente
con le opzioni socket SO_RCVBUF e SO_SNDBUF.
Per le versioni del kernel Linux 6.18 e successive, net.core.rmem_max e
net.core.wmem_max sono impostati su 4 MB per impostazione predefinita. Basate su anni di esperienza, queste
impostazioni sono considerate sicure. Per le versioni precedenti di Linux, ti consigliamo di
aumentare questi limiti a 4 MB sulle piattaforme moderne:
echo 4194304 > /proc/sys/net/core/rmem_max
echo 4194304 > /proc/sys/net/core/wmem_max
Il secondo insieme di limiti, net.ipv4.tcp_rmem e net.ipv4.tcp_wmem, gestisce
i limiti di ottimizzazione automatica del buffer di invio e ricezione TCP.
Ciascuna di queste impostazioni accetta tre valori: dimensioni minime, predefinite iniziali e massime della memoria del socket. I valori massimi predefiniti sono spesso più conservativi del necessario sulle piattaforme moderne, ad esempio:
tcp_rmem: 4096, 131072, 6291456tcp_wmem: 4096, 16384, 4194304
Lo stack TCP dimensiona automaticamente i buffer di invio e ricezione TCP in base alle stime di RTT e della finestra di congestione. Una dimensione massima del buffer di scrittura di 4194304, ovvero 4 MB, è piccola per le connessioni RTT elevate; con un RTT di 100 ms, questa impostazione limita la velocità effettiva a 40 MB/s nel migliore dei casi. Anziché cercare di calcolare i valori da utilizzare, un approccio più semplice consiste nell'utilizzare valori predefiniti sicuri per i server moderni con molti GB di RAM.
Come ulteriore precauzione, ti consigliamo di limitare la quantità di dati che possono essere
messi in coda nel socket ma non ancora inviati. Sebbene l'obiettivo di aumentare il valore massimo di
wmem sia quello di consentire il trasferimento di più dati, un processo può scrivere nella socket più velocemente
di quanto TCP possa inviarli, causando l'accumulo di una coda di dati non inviati sull'host e
lo spreco di memoria. Per evitare questo problema, limita la quantità di dati non ancora inviati impostando
tcp_notsent_lowat, quindi aumenta il limite complessivo di wmem per consentire
buffer in transito più grandi.
A meno che un server non abbia milioni di connessioni, le seguenti impostazioni dovrebbero essere sicure. Tuttavia, se si verificano condizioni di esaurimento della memoria con molte connessioni, utilizza una dimensione massima del buffer inferiore.
echo 4194304 > /proc/sys/net/ipv4/tcp_notsent_lowat
echo "4096 262144 16777216" > /proc/sys/net/ipv4/tcp_rmem
echo "4096 262144 33554432" > /proc/sys/net/ipv4/tcp_wmem
Attivare GRO hardware
Aumenta l'efficienza dell'elaborazione della ricezione TCP/IP per i flussi di grandi dimensioni. Ridurre l'overhead della CPU raggruppando i pacchetti ricevuti
Per la maggior parte delle operazioni TCP/IP, il costo del ciclo della CPU aumenta in base alla velocità dei pacchetti, non alla velocità in byte. Per ridurre questo overhead sulla trasmissione, i sistemi operativi moderni inviano dati TCP attraverso il percorso di trasmissione in pacchetti di grandi dimensioni che contengono più segmenti TCP. Questi possono variare fino a 64 kB o anche centinaia di kilobyte con Linux BIG-TCP.
Pacchetti così grandi superano la dimensione massima del pacchetto sulla rete, ovvero l'MTU. Questa ottimizzazione del sistema operativo si basa sul supporto dei dispositivi di rete per dividere questi pacchetti e inviarli come una serie di pacchetti più piccoli, ognuno dei quali contiene un singolo segmento TCP. Questo supporto, TCP Segmentation Offload (TSO), è ampiamente disponibile e attivato per impostazione predefinita.
Al momento della ricezione, i dispositivi gVNIC sulle piattaforme di terza generazione e successive possono eseguire l'operazione inversa: memorizzare brevemente nel buffer i segmenti nel dispositivo per verificare se arrivano segmenti consecutivi e, in caso affermativo, combinarli e inoltrarli come pacchetti multi-segmento all'host. Questa funzionalità è nota come Receive Segment Coalescing (RSC) in Windows, Large Receive Offload (LRO) o Hardware Generic Receive Offload (HW-GRO) in Linux. HW-GRO è un perfezionamento più rigoroso di LRO.
L'abilitazione predefinita di HW-GRO è sicura. Ciò avviene alla fine dove disponibile.
Nel frattempo, sulle piattaforme con dispositivi GVNIC che supportano la funzionalità, attiva HW-GRO utilizzando ethtool. A seconda della versione del kernel e del driver, la funzionalità viene pubblicizzata come LRO o HW-GRO. L'implementazione è la stessa indipendentemente dal nome.
ethtool -K $DEV large-receive-offload on
ethtool -K $DEV rx-gro-hw on
Aumenta le dimensioni MTU a 4082 byte
Aumenta l'efficienza del trasferimento dei dati per i flussi con velocità effettiva elevata.
L'aumento delle dimensioni dei pacchetti, in modo simile alle ottimizzazioni TSO e HW-GRO, aumenta l'efficienza del trasferimento perché la maggior parte del lavoro di elaborazione viene eseguita per pacchetto, non per byte.
Google Cloud Le reti VPC possono supportare pacchetti fino a 8898 byte, un valore molto più grande dell'MTU predefinita di 1460 byte. L'utilizzo di una dimensione del pacchetto di rete più grande riduce i cicli della CPU spesi per byte di velocità effettiva (goodput).
Considerazioni sulla dimensione ottimale del pacchetto
Anche se i pacchetti più grandi sono generalmente migliori, l'MTU massima possibile non è sempre la scelta ottimale. L'efficienza ottenuta dall'invio di un numero inferiore di pacchetti deve essere bilanciata con i seguenti costi:
- Utilizzo della memoria: i buffer più grandi richiedono più memoria assegnata al dispositivo di rete per la ricezione dei pacchetti. Se hai molte code, una quantità considerevole di memoria può rimanere inutilizzata (stranded).
- Gestione di pacchetti di piccole dimensioni: i buffer più grandi gestiscono i pacchetti di piccole dimensioni, come gli ACK puri, in modo meno efficiente.
- Costi di allocazione della CPU: i costi del percorso dei dati sono influenzati in modo significativo dall'allocazione e dalla liberazione della memoria. L'allineamento delle dimensioni del pacchetto a un multiplo di pagine di memoria consente di ottimizzare questo costo della CPU.
- Interazione TSO: le dimensioni dei pacchetti influiscono leggermente sul trasferimento della segmentazione TCP (TSO). Per creare il pacchetto TSO più grande possibile, potrebbe essere necessario scegliere una dimensione massima del segmento (MSS) più piccola. Ad esempio, dato il pacchetto IP più grande possibile di 64 KB, inclusi gli header, un MSS di 4 KB genera un payload più grande (60 KB) rispetto a un MSS di 8 KB (56 KB).
Per la maggior parte dei carichi di lavoro, la differenza di efficienza tra MTU da 4 KB, 8 KB o 9 KB è minima. Tuttavia, ognuno di questi rappresenta un miglioramento significativo rispetto ai pacchetti predefiniti da 1460 byte.
Consiglio per i pacchetti di dimensioni della pagina
In quanto opzione solida e generalmente efficiente, ti consigliamo di impostare le dimensioni MTU per la tua rete VPC su 4082 byte. Questa dimensione è consigliata perché consente all'intero pacchetto Ethernet di rientrare in una pagina di memoria di 4096 byte, il che ottimizza l'allocazione delle pagine di memoria. Questo consiglio riguarda l'MTU di livello 3, che include l'intestazione IP, ma esclude il livello di collegamento Ethernet di 14 byte.
Configurazione MTU IP
Puoi configurare l'MTU per ogni rete VPC direttamente tramite la console Google Cloud .
Per la maggior parte delle distribuzioni Linux in Google Cloud, non è necessaria alcuna configurazione manuale sull'istanza di calcolo. L'istanza apprende automaticamente l'MTU di rete utilizzando DHCP durante l'avvio (utilizzando l'opzione 26). L'istanza imposta quindi l'MTU del dispositivo di rete in modo che corrisponda. Ti consigliamo di utilizzare questa configurazione automatica.
Se è necessaria la configurazione manuale, l'MTU del dispositivo di rete può essere impostato su un valore inferiore all'MTU della rete VPC utilizzando il seguente comando:
ip link set dev $DEV mtu 4082
Imposta dimensioni MTU diverse per route specifiche
Se la tua istanza di calcolo comunica esternamente al di fuori del VPC, dove la MTU del percorso potrebbe essere inferiore, l'impostazione della MTU su route specifiche è l'opzione preferita. In questo scenario, imposta l'MTU predefinita sul valore conservativo di 1460 byte e applica l'MTU più elevata, ad esempio 4082 byte, solo per le route intra-VPC:
#Set intra-VPC route MTU:
ip -4 route change $SUBNET/$MASK dev $DEV mtu 4082
#Set default route MTU:
ip -4 route change default dev $DEV mtu 1460
Configura la dimensione massima del segmento (MSS) TCP
La dimensione massima del segmento (MSS) TCP determina le dimensioni del payload del pacchetto per una connessione TCP. Poiché i pacchetti TCP/IP non devono superare le dimensioni MTU per evitare la frammentazione o l'eliminazione dei pacchetti, l'MSS deve essere scalato di conseguenza.
In generale, non è necessario configurare manualmente TCP MSS, perché il sistema operativo lo deriva automaticamente dall'MTU del percorso.
MSS copre le opzioni di payload e TCP, ma esclude l'intestazione IPv4 di 20 byte e l'intestazione TCP di 20 byte. Pertanto, su una rete IPv4, l'MSS è in genere 40 byte più piccolo dell'MTU.
Se preferisci un MSS più piccolo per un traffico specifico, puoi configurarlo in base alla route. Ad esempio, se la rete VPC e l'MTU del dispositivo utilizzano il valore massimo (8896 byte) per il traffico generale, ma vuoi utilizzare l'MTU di 4 KB per il traffico TCP, puoi utilizzare il seguente comando:
ip -4 route change default dev $DEV advmss 4042
Modalità di divisione dell'intestazione
Le piattaforme di terza generazione offrono una funzionalità facoltativa di divisione dell'intestazione di ricezione, che è disabilitata per impostazione predefinita.
La suddivisione dell'intestazione separa le intestazioni e i dati dei pacchetti in buffer distinti. Ciò consente di riempire un'intera pagina di memoria con 4096 byte di dati. Questa
separazione consente ottimizzazioni cruciali, come la sostituzione di costose
operazioni di copia dal kernel allo spazio utente con operazioni di mappatura delle pagine di memoria più economiche (ad esempio, utilizzando Linux TCP_ZEROCOPY_RECEIVE).
Quando la funzionalità di suddivisione dell'intestazione di ricezione è abilitata, il calcolo dell'MTU cambia. L'MTU ottimale è quella in cui tutte le intestazioni vengono mappate nel buffer di intestazione e il buffer del payload riempie un'intera pagina di dati. Con la suddivisione dell'intestazione attivata:
- Un buffer di intestazione contiene:
- Ethernet (14 byte)
- IPv4 (20 byte)
- Intestazioni TCP (20 byte)
- Opzioni TCP comuni (12 byte per la configurazione predefinita con timestamp TCP)
- Il buffer di dati contiene 4096 byte di dati utili.
Il risultato è una dimensione totale del frame di 4162 byte e quindi un MTU di 4148 byte.
Passaggi successivi
- Leggi il blog post su 5 steps to better Google Cloud networking performance.
- Scopri di più sui prodotti Global Networking.
- Scopri di più sui livelli di rete su Google Cloud.
- Scopri come eseguire il benchmarking delle prestazioni di rete.