Ottimizzazione del Throughput di Rete Linux tramite la Regolazione dei Parametri sysctl TCP/IP
Regolazione pratica dei sysctl TCP di Linux per throughput, buffer, controllo della congestione e test sicuri.
Ottimizzazione del Throughput di Rete Linux tramite la Regolazione dei Parametri sysctl TCP/IP
L'ottimizzazione del throughput di rete Linux inizia con una domanda noiosa: cosa è effettivamente lento? Un server che raggiunge al massimo 300 Mbps su un collegamento da 10 Gbps potrebbe avere un problema di finestra TCP, un problema di disco, un problema di interrupt della CPU, un'impostazione errata della scheda di rete virtuale, un problema di perdita di pacchetti o un'applicazione che invia dati in piccoli frammenti. La regolazione di sysctl aiuta solo con alcuni di questi.
Ecco perché tratto le modifiche sysctl TCP/IP come esperimenti controllati, non come ricette magiche per le prestazioni. Inizia con una baseline, modifica un piccolo gruppo di impostazioni, testa di nuovo e prendi appunti. Se copi un enorme blocco di ottimizzazione da Internet in /etc/sysctl.conf, potresti migliorare un carico di lavoro e danneggiarne silenziosamente un altro.
Le impostazioni seguenti sono utili quando esegui servizi ad alto throughput: repository di artefatti, server di backup, gateway di object storage, proxy inversi molto trafficati, repliche di database che inviano grandi log o host Linux che spostano traffico su collegamenti a lunga distanza. È meno probabile che aiutino se il tuo collo di bottiglia è la CPU di crittografia TLS, lo storage lento, il locking dell'applicazione, i limiti del provider cloud o la perdita di pacchetti al di fuori dell'host.
Prima di modificare qualsiasi cosa, raccogli una baseline rapida:
ip -s link
ss -s
nstat -az | egrep 'TcpRetransSegs|TcpExtTCPLoss|TcpExtTCPTimeouts|TcpExtListenOverflows'
sar -n DEV,TCP,ETCP 1 10
iperf3 -c test-host -P 4 -t 30
Se vedi aumentare le ritrasmissioni, risolvi la perdita prima di aumentare i buffer. Se la CPU è già al massimo in top, mpstat o perf, i sysctl potrebbero nascondere il sintomo ma non rimuovere il collo di bottiglia. Se iperf3 è veloce ma la tua app è lenta, guarda il percorso dell'app prima di ottimizzare il kernel.
Come sysctl si Inserisce nell'Ottimizzazione di Rete
sysctl espone i parametri del kernel mentre il sistema è in esecuzione. Le impostazioni di rete di solito si trovano sotto net.ipv4, net.ipv6 e net.core. Puoi leggere un valore in questo modo:
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_rmem
sysctl net.core.rmem_max
Puoi testare una modifica temporanea in questo modo:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Le modifiche temporanee scompaiono dopo il riavvio. Le modifiche permanenti vanno in un file dedicato come /etc/sysctl.d/90-network-throughput.conf, non sparse in /etc/sysctl.conf senza spiegazioni.
sudo install -m 0644 /dev/null /etc/sysctl.d/90-network-throughput.conf
sudo editor /etc/sysctl.d/90-network-throughput.conf
sudo sysctl --system
Usa un file separato perché il rollback è semplice: sposta il file ed esegui di nuovo sudo sysctl --system. Questo è importante quando un'impostazione si comporta male sotto traffico di produzione.
Buffer TCP: Dai Spazio per Respirare alle Connessioni Lunghe
Il primo posto dove la gente guarda è la dimensione dei buffer. TCP ha bisogno di spazio sufficiente nella finestra di invio e ricezione per mantenere i dati in volo mentre gli acknowledgment viaggiano attraverso la rete. Il modello mentale utile è il prodotto larghezza di banda-ritardo: una connessione ad alta larghezza di banda e alta latenza ha bisogno di più dati in volo rispetto a una connessione LAN a bassa latenza.
Ad esempio, un trasferimento da 1 Gbps su un percorso del data center con 1 ms di latenza ha bisogno di molti meno dati in volo rispetto a un trasferimento da 1 Gbps su un percorso WAN con 70 ms di latenza. Se la finestra di ricezione è troppo piccola, il mittente si ferma anche se il collegamento ha spazio.
Linux utilizza array di tre valori per la regolazione della memoria TCP:
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
I tre numeri sono le dimensioni minime, predefinite e massime del buffer per socket in byte. I valori esatti dovrebbero corrispondere al tuo carico di lavoro, al budget di memoria e al comportamento del kernel. L'esempio sopra aumenta il massimo a 32 MiB, che è spesso sufficiente per server occupati senza essere sconsiderato. Alcuni sistemi a lungo raggio o con carichi pesanti di storage utilizzano valori più grandi, ma questo dovrebbe essere testato con traffico reale.
I limiti net.core limitano i buffer dei socket:
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
Se tcp_rmem dice che TCP può crescere fino a 32 MiB ma net.core.rmem_max è molto più basso, il limite inferiore vince nella pratica. Mantieni i limiti allineati con i massimi TCP a meno che tu non abbia un motivo per non farlo.
Non aumentare i buffer alla cieca su una macchina con molte connessioni concorrenti. Un file server con pochi flussi di grandi dimensioni può permettersi buffer per flusso più grandi. Un proxy che gestisce centinaia di migliaia di connessioni può bruciare memoria rapidamente se rendi ogni socket idoneo per buffer enormi.
L'Autotuning Sta Già Facendo Parte del Lavoro
I kernel Linux moderni eseguono già l'autotuning dei buffer TCP. Ciò significa che di solito non è necessario impostare buffer socket fissi enormi nell'applicazione. Il kernel fa crescere i buffer quando una connessione beneficia di più spazio.
Il tuo compito è principalmente assicurarti che il soffitto non sia troppo basso. Se il throughput è scarso su una rete lunga e spessa e ss -tin mostra finestre di ricezione piccole o un mittente bloccato dal ricevitore, aumentare tcp_rmem, tcp_wmem, rmem_max e wmem_max può aiutare.
Controlla le connessioni attive con:
ss -tin dst <ip-peer>
Cerca campi come cwnd, rtt, rto, bytes_acked, bytes_received e contatori di ritrasmissione. Raccontano una storia migliore di un singolo test di velocità.
Controllo della Congestione: CUBIC, BBR e Realtà
L'algoritmo di controllo della congestione decide come TCP aumenta o diminuisce la sua velocità di invio. Su molti sistemi Linux, CUBIC è l'impostazione predefinita e funziona bene per il traffico Internet generale e dei data center. BBR può migliorare il throughput e la latenza su alcuni percorsi con perdite o a lunga distanza perché modella la larghezza di banda del collo di bottiglia e il tempo di andata e ritorno invece di reagire solo alla perdita di pacchetti.
Controlla gli algoritmi disponibili:
sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control
Abilita BBR solo se il tuo kernel lo ha disponibile:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Per la persistenza:
net.ipv4.tcp_congestion_control = bbr
Alcuni sistemi richiedono anche lo scheduler dei pacchetti con fair queuing per un buon comportamento di BBR:
net.core.default_qdisc = fq
Non dare per scontato che BBR sia sempre più veloce. Può cambiare l'equità con altri flussi e diverse versioni di BBR si comportano diversamente tra i kernel. Testalo sullo stesso modello di traffico che ti interessa: molte piccole chiamate API, pochi trasferimenti bulk, traffico di database replicato o carico misto simile alla produzione.
Code di Ascolto: Risolvi le Perdite Prima che Diventino Misteri
I problemi di throughput a volte si manifestano come fallimenti di connessione durante i picchi di traffico. Se un servizio accetta nuove connessioni TCP più lentamente di quanto i client le creino, le code del kernel si riempiono.
Impostazioni rilevanti:
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
somaxconn limita il backlog di connessioni completate richiesto dalle applicazioni tramite listen(2). tcp_max_syn_backlog influisce sulla capacità della coda SYN semi-aperta. Aumentarli può aiutare server web, proxy e bilanciatori di carico molto trafficati, ma l'applicazione deve anche richiedere un backlog sufficientemente grande. Nginx, HAProxy, Envoy e i server applicativi hanno spesso le proprie impostazioni di backlog.
Tieni d'occhio gli overflow:
nstat -az | egrep 'ListenOverflows|ListenDrops|Syncookies'
ss -ltn
Se ListenOverflows aumenta, le code del kernel non tengono il passo. Se la CPU è satura o l'app è bloccata sui servizi a valle, aumentare le dimensioni delle code può ridurre brevemente gli errori del client ma non risolverà il servizio.
Backlog ed Elaborazione dei Pacchetti
net.core.netdev_max_backlog controlla quanti pacchetti possono attendere nella coda di input quando il kernel riceve pacchetti più velocemente di quanto possa elaborarli.
net.core.netdev_max_backlog = 250000
Questo può aiutare su interfacce ad alta velocità durante i burst, specialmente con reti virtualizzate. Può anche aggiungere latenza se trasformi l'host in una grande sala d'attesa per pacchetti. Controlla prima le perdite dell'interfaccia:
ip -s link show dev eth0
ethtool -S eth0 | egrep 'drop|err|timeout|miss|fifo'
Se le perdite a livello di driver aumentano, ispeziona anche le dimensioni degli anelli della NIC, la distribuzione degli interrupt, le code RSS e l'affinità della CPU. Questi sono al di fuori di sysctl, ma spesso contano più dei buffer TCP su host da 10 Gbps e più veloci.
TIME_WAIT ed Esaurimento delle Porte
Client, proxy e job runner ad alto throughput possono esaurire le porte effimere o accumulare molti socket in TIME_WAIT. Fai attenzione qui perché i vecchi consigli di ottimizzazione possono essere dannosi.
Controlla l'intervallo corrente:
sysctl net.ipv4.ip_local_port_range
ss -tan state time-wait | wc -l
Un aggiustamento ragionevole lato client è ampliare l'intervallo delle porte effimere:
net.ipv4.ip_local_port_range = 10240 60999
Evita i vecchi consigli che raccomandano tcp_tw_recycle; è stato rimosso da Linux perché rompeva il traffico valido, specialmente dietro NAT. tcp_tw_reuse esiste su molti kernel, ma il suo comportamento è cambiato nel tempo. Non abilitarlo come impostazione predefinita per il throughput. Se pensi di averne bisogno, testa attentamente il tuo kernel esatto e il modello di traffico.
Per i server, un mucchio di socket TIME_WAIT è spesso normale. Per i client, l'esaurimento delle porte di solito significa che hai bisogno di connection pooling, keep-alive, HTTP/2, meno connessioni in uscita di breve durata o più IP di origine.
Un File di Partenza Conservativo
Ecco un punto di partenza pratico per un server ad alto throughput. Non è intenzionalmente estremo:
# /etc/sysctl.d/90-network-throughput.conf
# Soffitti di autotuning TCP più grandi per percorsi ad alta larghezza di banda o latenza più elevata.
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
# Code più grandi per traffico in entrata a raffica.
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 250000
# Opzionale: testa prima di abilitare globalmente.
# net.core.default_qdisc = fq
# net.ipv4.tcp_congestion_control = bbr
Applicalo:
sudo sysctl --system
Poi misura di nuovo. Usa la stessa dimensione del test, finestra temporale, numero di flussi paralleli e percorso di rete. Un test prima e dopo che cambia cinque variabili non è una prova.
Errori Comuni
Il primo errore è ottimizzare su un percorso con perdite. TCP vede la perdita come congestione. Buffer più grandi possono aumentare leggermente il throughput, ma possono anche aumentare la latenza e nascondere il problema reale. Risolvi prima cavi difettosi, switch virtuali sovraccarichi, policing dei pacchetti, disallineamento MTU e percorsi VPN instabili.
Il secondo errore è presumere che iperf3 -P 8 provi le prestazioni dell'applicazione. Flussi paralleli possono riempire un collegamento anche quando una singola connessione applicativa reale non può. Questa è un'informazione utile, ma non è tutta la storia.
Il terzo errore è impostare buffer enormi su host condivisi. Soffitti più grandi vanno bene quando il kernel fa crescere i buffer solo quando necessario, ma la pressione della memoria cambia tutto. Monitora free, slabtop, la memoria TCP e la memoria dell'applicazione dopo le modifiche.
Il quarto errore è dimenticare il rollback. Mantieni i valori precedenti nel tuo ticket di modifica o runbook:
sysctl -a | egrep 'net.core.rmem_max|net.core.wmem_max|net.ipv4.tcp_rmem|net.ipv4.tcp_wmem|net.ipv4.tcp_congestion_control'
Quando sysctl Non è la Soluzione
Se un core della CPU è al massimo mentre gli altri sono inattivi, guarda la gestione degli interrupt, RSS, RPS/XPS e il threading dell'applicazione. Se l'attesa del disco è alta, la rete potrebbe essere in attesa dello storage. Se TLS consuma CPU, testa con e senza crittografia e considera l'hardware, la scelta del cifrario o il riutilizzo della connessione. Se Kubernetes o un load balancer cloud si trovano nel percorso, controlla i limiti a livello di servizio e le tabelle conntrack.
Per host con molto NAT, ispeziona anche conntrack:
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
Non è ottimizzazione del throughput TCP, ma l'esaurimento di conntrack può sembrare lentezza di rete casuale o connessioni interrotte.
Testare Senza Ingannare Te Stesso
Usa iperf3 come strumento di rete, non come prova che l'applicazione sia stata risolta. Un test a flusso singolo è utile perché mostra cosa può fare una singola connessione TCP:
iperf3 -c test-host -t 30
Un test parallelo mostra se il collegamento può essere riempito da più flussi:
iperf3 -c test-host -P 8 -t 30
Se i flussi paralleli sono veloci ma un singolo flusso è lento, guarda il controllo della congestione, la crescita della finestra TCP, RTT e la perdita di pacchetti. Se entrambi sono lenti, guarda più in basso: errori dell'interfaccia, limiti di larghezza di banda del cloud, saturazione della CPU, MTU, ispezione del firewall o storage dietro il mittente e il ricevitore.
Mantieni il percorso di test realistico. Testare due host nello stesso rack non ti dirà molto su un lavoro di backup che attraversa le regioni. Testare con un file minuscolo non esporrà il throughput in stato stazionario. Testare attraverso una VPN potrebbe misurare più l'appliance VPN che il TCP Linux.
Dopo ogni modifica, cattura gli stessi contatori:
nstat -az > /tmp/nstat-after.txt
ss -s
sar -n DEV,TCP,ETCP 1 10
Il risultato utile non è solo "il numero è aumentato". Vuoi sapere se le ritrasmissioni sono diminuite, le code hanno smesso di traboccare, la CPU è rimasta ragionevole e la latenza non è peggiorata per le richieste più piccole.
Una buona ottimizzazione della rete Linux è misurata e reversibile. Aumenta i soffitti dei buffer TCP quando il percorso ha bisogno di finestre più grandi. Testa il controllo della congestione invece di presumere che un algoritmo vinca ovunque. Aumenta le code di ascolto quando vedi cadute di coda e risolvi l'applicazione se non riesce ad accettare abbastanza velocemente. sysctl è utile, ma è uno strato in un sistema più grande.