La rete globale in Cloud de Confiance offre elevata affidabilità e bassa latenza collegando le applicazioni tra regioni e zone 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 migliori prestazioni in Cloud de Confiance by S3NS, utilizza le impostazioni TCP/IP descritte 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' Cloud de Confiance ambiente. 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 comporta un sottoutilizzo delle moderne reti ad alta velocità, poiché il mittente attende gli aggiornamenti della finestra.
Script shell per ottimizzare le prestazioni TCP
Per migliorare le prestazioni, ti consigliamo di utilizzare le seguenti configurazioni TCP:
- Riduci MinRTO: recupera più velocemente dalla perdita di pacchetti riducendo i ritardi di ritrasmissione.
- Abilita Fair Queueing: riduci al minimo la congestione e le perdite dovute a picchi di traffico delle applicazioni.
- Disabilita l'avvio lento dopo l'inattività: riavvia all'ultima velocità di trasferimento nota come buona dopo un periodo di inattività della connessione.
- Disabilita 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 delle 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 i 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 abilitare 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 computing.
# 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 dettaglio ciascuna delle impostazioni di configurazione suggerite.
Riduci MinRTO
Recupera più velocemente dalla perdita di pacchetti riducendo i ritardi di ritrasmissione.
Il timeout di ritrasmissione TCP (RTO) controlla per quanto tempo un mittente TCP attende un segnale ACK prima di ritrasmettere. Linux inizializza l'RTO a un secondo (in base alla sezione 2.1 del documento RFC 6298), quindi lo regola nel tempo in base al tempo di round trip (RTT) più un margine di sicurezza.
Il valore minimo di RTO (MinRTO) implementa un limite inferiore per questa regolazione. Se la stima dell'RTO è troppo bassa, può introdurre ritrasmissioni spurie, in cui il mittente ritrasmette i pacchetti mentre la risposta è ancora in corso.
Il valore MinRTO predefinito è 200 ms, che è inutilmente conservativo per le moderne reti cloud. Un valore di 5 ms è stato ampiamente testato in Cloud de Confiance ed è un valore predefinito sicuro per le connessioni tra i moderni server Linux in Cloud de Confiance.
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 inversa. I timer ACK ritardati si basano sull'RTT, in modo simile al timer RTO.
La riduzione del valore MinRTO accelera la riparazione delle perdite sulle connessioni con RTT basso, ad esempio le connessioni all'interno di una zona o regione. Questa regolazione non influisce sul comportamento delle connessioni che presentano un RTT elevato, in quanto non modifica l'RTT stimato.
Configurazione di MinRTO
Puoi configurare MinRTO utilizzando uno dei due metodi seguenti:
Utilizzando
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=5000Utilizzando
ip route(controllo per route o versioni di Linux precedenti alla 6.11):In alternativa, per le versioni di Linux precedenti o per il controllo per route, MinRTO può essere impostato per ogni route:
ip route change default rto_min 5ms
L'approccio per route è preferibile negli ambienti in cui le connessioni potrebbero uscire Cloud de Confiance o comunicare con stack TCP/IP non Linux. Questi sistemi potrebbero avere timer ACK ritardati diversi. Per un deployment su internet pubblico ampio, ti consigliamo di mantenere l'impostazione MinRTO predefinita conservativa e di applicare l'impostazione di 5 ms solo per le route all'interno del Cloud de Confiance Virtual Private Cloud (VPC).
Abilita Fair Queueing
Riduci al minimo la congestione e le perdite di pacchetti causate da 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 consegna ottimali per ogni pacchetto. Se FQ è presente, lo stack TCP si basa su FQ per conservare i pacchetti fino al tempo di consegna ottimale. Questa regolazione riduce i picchi di traffico all'interno di un flusso, il che a sua volta riduce al minimo le perdite di pacchetti e le ritrasmissioni.
Per impostare il regolatore del traffico FQ come regolatore del traffico del dispositivo di rete, utilizza il seguente comando tc (controllo del traffico):
tc qdisc replace dev $DEV root fq
Nelle istanze di grandi dimensioni con larghezza di banda in uscita elevata, il dispositivo di rete potrebbe avere più code di trasmissione. Per queste istanze, potrebbe essere preferibile suddividere il formato di traffico tra le code di trasmissione installando il regolatore del formato di traffico Multi Queue (MQ). Si tratta di un multiplexer che collega un regolatore del traffico indipendente a ogni coda di trasmissione. I regolatori del traffico per coda riducono il conflitto sui blocchi e sulle cacheline tra le CPU.
Disabilita l'avvio lento dopo l'inattività
Mantieni velocità di trasferimento elevate dopo che una connessione è rimasta inattiva.
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 di "avvio lento" dopo un periodo di inattività. Un periodo di inattività può essere breve come un timeout di ritrasmissione (RTO), come definito nel documento RFC 2581. La disabilitazione di questa funzionalità consente alla connessione di riprendere immediatamente alla velocità nota come buona.
Ove possibile, le applicazioni devono utilizzare connessioni di lunga durata anziché stabilire ripetutamente la connessione allo stesso peer. In questo modo si evita il costo di stabilire la connessione e si mantengono le informazioni sulla congestione. Tuttavia, anche con le connessioni di lunga durata, dopo un periodo di inattività TCP dimentica le informazioni sulla congestione per impostazione predefinita e torna all'impostazione conservativa iniziale e alla fase di "avvio lento".
Per disabilitare la funzionalità di avvio lento dopo l'inattività, utilizza il seguente comando:
sysctl -w net.ipv4.tcp_slow_start_after_idle=0
Disabilita il treno di ACK TCP Cubic HyStart
Aumenta rapidamente le velocità di trasferimento elevate ignorando i segnali di congestione falsi positivi.
La velocità di crescita esponenziale della fase di "avvio lento" può essere aggressiva, superando potenzialmente la velocità target ottimale. Hybrid Start (HyStart) è un meccanismo aggiuntivo progettato per uscire dalla fase di "avvio lento" in anticipo utilizzando due segnali di congestione chiave:
- 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 con colli di bottiglia. Ciò causa l'aumento dell'RTT, che può segnalare la presenza di congestione.
- Spaziatura ACK: si basa sui segnali che indicano 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 arrivino con la stessa spaziatura dei pacchetti di dati originali. Questo pattern viene spesso definito treno di ACK. Se gli ACK vengono ritardati oltre questo pattern previsto, significa che potrebbe essere presente congestione.
Per ottimizzare le prestazioni, disabilita il rilevamento del treno di pacchetti ACK mantenendo abilitato il meccanismo di ritardo RTT.
echo 2 > /sys/module/tcp_cubic/parameters/hystart_detect
Aumenta i budget di memoria delle socket
Aumenta la velocità effettiva massima 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 prendendo la larghezza di banda e moltiplicandola per il tempo di round trip (RTT): si ottiene 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 delle socket TCP possono limitare direttamente la velocità effettiva raggiungibile determinando la quantità di dati in transito che può essere memorizzata nel buffer.
In Linux, i limiti di memoria delle 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 delle socket TCP esistono per evitare di utilizzare tutta la memoria di sistema e causare condizioni di memoria insufficiente (OOM), soprattutto nei carichi di lavoro con molte connessioni. L'aumento di questi limiti può aumentare la velocità effettiva, soprattutto sui percorsi con RTT elevato. A meno che il numero di connessioni non sia di milioni, non c'è alcun rischio nell'aumentare questi limiti.
Queste variabili impostano i limiti superiori per le dimensioni del buffer delle 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 Cloud de Confiance zona.
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 delle 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 hanno come valore predefinito 4 MB. In base a anni di esperienza, queste impostazioni sono considerate sicure. Per le versioni di Linux precedenti, 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 set di limiti, net.ipv4.tcp_rmem e net.ipv4.tcp_wmem, gestisce i limiti di regolazione automatica del buffer di invio e ricezione TCP.
Ciascuna di queste impostazioni accetta tre valori: dimensione minima, predefinita iniziale e massima della memoria delle 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 regola automaticamente le dimensioni dei buffer di invio e ricezione TCP in base alle stime dell'RTT e della finestra di congestione. Una dimensione massima del buffer di scrittura di 4194304, ovvero 4 MB, è piccola per le connessioni con RTT elevato; con un RTT di 100 ms, questa impostazione limita la velocità effettiva a 40 MB/s nel caso migliore. Invece di provare a calcolare i valori da utilizzare, un approccio più semplice consiste nell'utilizzare valori predefiniti sicuri per i server moderni che dispongono di molti GB di RAM.
Come precauzione aggiuntiva, ti consigliamo di limitare la quantità di dati che possono essere accodati nella socket ma non ancora inviati. Sebbene l'obiettivo di aumentare il valore massimo di wmem sia quello di consentire un maggior numero di dati in transito, 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 memoria insufficiente 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
Abilita GRO hardware
Aumenta l'efficienza dell'elaborazione di ricezione TCP/IP per i flussi di grandi dimensioni. Riduci l'overhead della CPU raggruppando i pacchetti ricevuti
Per la maggior parte delle operazioni TCP/IP, il costo dei cicli della CPU aumenta con la velocità dei pacchetti, non con la velocità dei byte. Per mitigare questo overhead sulla trasmissione, i sistemi operativi moderni inviano i 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.
Questi pacchetti di grandi dimensioni superano la dimensione massima dei pacchetti sulla rete, ovvero l'MTU. Questa ottimizzazione del sistema operativo si basa sul supporto del dispositivo di rete per suddividere questi pacchetti e inviarli come un treno di pacchetti più piccoli, ognuno contenente un singolo segmento TCP. Questo supporto, TCP Segmentation Offload (TSO), è ampiamente disponibile e abilitato per impostazione predefinita.
Al momento della ricezione, i dispositivi GVNIC sulle piattaforme di terza generazione e successive possono eseguire l'operazione inversa: memorizzare brevemente i segmenti nel buffer del dispositivo per verificare se arrivano segmenti consecutivi e, in caso affermativo, combinarli e inoltrarli all'host come pacchetti multi-segmento. 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.
HW-GRO può essere abilitato per impostazione predefinita. Questo avviene alla fine, se disponibile.
Nel frattempo, sulle piattaforme con dispositivi GVNIC che supportano la funzionalità, abilita 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 dell'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.
Cloud de Confiance Le reti VPC possono supportare pacchetti fino a 8898 byte, che è significativamente più grande dell'MTU predefinito di 1460 byte. L'utilizzo di una dimensione dei pacchetti di rete più grande riduce i cicli della CPU spesi per byte di velocità effettiva (goodput).
Considerazioni sulle dimensioni ottimali dei pacchetti
Sebbene i pacchetti più grandi siano generalmente migliori, l'MTU massimo 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 una maggiore quantità di memoria assegnata al dispositivo di rete per la ricezione dei pacchetti. Se hai molte code, una quantità significativa di memoria può rimanere inutilizzata (bloccata).
- Gestione dei pacchetti piccoli: i buffer più grandi gestiscono i pacchetti piccoli, come gli ACK (acknowledgement) puri, in modo meno efficiente.
- Costi di allocazione della CPU: i costi del datapath sono influenzati in modo significativo dall' allocazione e dalla liberazione della memoria. L'allineamento delle dimensioni dei pacchetti a un multiplo delle 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, incluse le intestazioni, 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 di 4 KB, 8 KB o 9 KB è piccola. Tuttavia, una qualsiasi di queste è un miglioramento significativo rispetto ai pacchetti predefiniti di 1460 byte.
Consigli per i pacchetti di dimensioni della pagina
Come opzione robusta e generalmente efficiente, ti consigliamo di impostare le dimensioni dell'MTU per la tua rete VPC su 4082 byte. Questa dimensione è consigliata perché consente di inserire l'intero pacchetto Ethernet 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 dell'MTU IP
Puoi configurare l'MTU per ogni rete VPC direttamente tramite la Cloud de Confiance console.
Per la maggior parte delle distribuzioni Linux in Cloud de Confiance, non è necessaria alcuna configurazione manuale sull'istanza di computing. 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 l'istanza di computing comunica esternamente al di fuori del VPC, dove l'MTU del percorso potrebbe essere inferiore, l'opzione preferita è impostare l'MTU su route specifiche. In questo scenario, imposta l'MTU predefinito sul valore conservativo di 1460 byte e applica l'MTU più elevato, 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 TCP (MSS)
La dimensione massima del segmento TCP (MSS) determina le dimensioni del payload del pacchetto per una connessione TCP. Poiché i pacchetti TCP/IP non devono superare le dimensioni dell'MTU per evitare la frammentazione o la perdita di pacchetti, l'MSS deve essere scalato di conseguenza.
In genere, non è necessario configurare manualmente l'MSS TCP, perché il sistema operativo lo deriva automaticamente dall'MTU del percorso.
L'MSS copre il payload e le opzioni 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 per ogni route. Ad esempio, se l'MTU della rete VPC e del dispositivo utilizza 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 suddivisione dell'intestazione
Il driver gve gVNIC nelle versioni del kernel Linux 6.9 e successive supporta la suddivisione dei dati dell'intestazione TCP (tcp-data-split), che è disabilitata per impostazione predefinita.
La suddivisione dell'intestazione separa le intestazioni e i dati dei pacchetti in buffer distinti. In questo modo è possibile riempire un'intera pagina di memoria con 4096 byte di dati. Questa separazione consente ottimizzazioni cruciali, ad esempio 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 TCP_ZEROCOPY_RECEIVE di Linux).
Quando la funzionalità di suddivisione dell'intestazione di ricezione è abilitata, il calcolo dell'MTU cambia. L'MTU ottimale è quello in cui tutte le intestazioni vengono mappate nel buffer dell'intestazione e il buffer del payload riempie un'intera pagina di dati. Con la suddivisione dell'intestazione abilitata:
- Un buffer dell'intestazione contiene:
- Intestazioni Ethernet (14 byte)
- Intestazioni IPv4 (20 byte)
- Intestazioni TCP (20 byte)
- Opzioni TCP comuni (12 byte per la configurazione predefinita con timestamp TCP)
- Il buffer dei dati contiene 4096 byte di dati del payload.
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 Cloud de Confiance networking performance.
- Scopri di più sui prodotti Global Networking.
- Scopri di più sui livelli di rete su Cloud de Confiance.
- Scopri come eseguire il benchmarking delle prestazioni di rete.