Otimizando a Taxa de Transferência de Rede Linux Ajustando Parâmetros sysctl TCP/IP
Ajuste prático de sysctl TCP no Linux para taxa de transferência, buffers, controle de congestionamento e testes seguros.
Otimizando a Taxa de Transferência de Rede Linux Ajustando Parâmetros sysctl TCP/IP
A otimização da taxa de transferência de rede Linux começa com uma pergunta chata: o que está realmente lento? Um servidor que atinge no máximo 300 Mbps em um link de 10 Gbps pode ter um problema de janela TCP, um problema de disco, um problema de interrupção de CPU, uma configuração ruim de NIC virtual, um problema de perda de pacotes ou um aplicativo que envia dados em pequenos fragmentos. O ajuste de sysctl só ajuda em alguns desses casos.
É por isso que trato as alterações de sysctl TCP/IP como experimentos controlados, não como receitas mágicas de desempenho. Comece com uma linha de base, altere um pequeno grupo de configurações, teste novamente e mantenha anotações. Se você copiar um bloco de ajuste gigante da internet para /etc/sysctl.conf, pode melhorar uma carga de trabalho e prejudicar silenciosamente outra.
As configurações abaixo são úteis quando você executa serviços de alta taxa de transferência: repositórios de artefatos, servidores de backup, gateways de armazenamento de objetos, proxies reversos ocupados, réplicas de banco de dados enviando grandes logs ou hosts Linux movendo tráfego em links de longa distância. É menos provável que ajudem se seu gargalo for CPU de criptografia TLS, armazenamento lento, bloqueio de aplicativo, limites do provedor de nuvem ou perda de pacotes fora do host.
Antes de mudar qualquer coisa, colete uma linha de base rápida:
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 você vir retransmissões aumentando, corrija a perda antes de aumentar os buffers. Se a CPU já estiver no limite em top, mpstat ou perf, os sysctls podem esconder o sintoma, mas não remover o gargalo. Se iperf3 for rápido, mas seu aplicativo for lento, olhe o caminho do aplicativo antes de ajustar o kernel.
Como o sysctl se Encaixa na Otimização de Rede
sysctl expõe parâmetros do kernel enquanto o sistema está em execução. As configurações de rede geralmente ficam em net.ipv4, net.ipv6 e net.core. Você pode ler um valor assim:
sysctl net.ipv4.tcp_congestion_control
sysctl net.ipv4.tcp_rmem
sysctl net.core.rmem_max
Você pode testar uma alteração temporária assim:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Alterações temporárias desaparecem após a reinicialização. Alterações persistentes pertencem a um arquivo dedicado, como /etc/sysctl.d/90-network-throughput.conf, não espalhadas pelo /etc/sysctl.conf sem explicação.
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
Use um arquivo separado porque a reversão é simples: mova o arquivo para outro lugar e execute sudo sysctl --system novamente. Isso é importante quando uma configuração se comporta mal sob tráfego de produção.
Buffers TCP: Dê Espaço para Conexões Longas Respirarem
O primeiro lugar onde as pessoas olham é o dimensionamento do buffer. O TCP precisa de espaço suficiente na janela de envio e recebimento para manter dados em trânsito enquanto as confirmações viajam pela rede. O modelo mental útil é o produto largura de banda-atraso: uma conexão de alta largura de banda e alta latência precisa de mais dados em trânsito do que uma conexão LAN de baixa latência.
Por exemplo, uma transferência de 1 Gbps em um caminho de datacenter de 1 ms precisa de muito menos dados em trânsito do que uma transferência de 1 Gbps em um caminho WAN de 70 ms. Se a janela de recebimento for muito pequena, o remetente pausa mesmo que o link tenha espaço.
O Linux usa arrays de três valores para ajuste de memória TCP:
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
Os três números são os tamanhos mínimo, padrão e máximo do buffer por soquete em bytes. Os valores exatos devem corresponder à sua carga de trabalho, orçamento de memória e comportamento do kernel. O exemplo acima aumenta o máximo para 32 MiB, o que geralmente é suficiente para servidores ocupados sem ser imprudente. Alguns sistemas de longa distância ou com uso intensivo de armazenamento usam valores maiores, mas isso deve ser testado com tráfego real.
Os limites net.core limitam os buffers do soquete:
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
Se tcp_rmem diz que o TCP pode crescer para 32 MiB, mas net.core.rmem_max é muito menor, o limite inferior vence na prática. Mantenha os limites alinhados com os máximos do TCP, a menos que você tenha um motivo para não fazer isso.
Não aumente os buffers cegamente em uma máquina com muitas conexões simultâneas. Um servidor de arquivos com alguns fluxos grandes pode pagar por buffers maiores por fluxo. Um proxy lidando com centenas de milhares de conexões pode queimar memória rapidamente se você tornar cada soquete elegível para buffers enormes.
O Ajuste Automático Já Está Fazendo Algum Trabalho
Os kernels Linux modernos já ajustam automaticamente os buffers TCP. Isso significa que você geralmente não precisa definir buffers de soquete fixos enormes no aplicativo. O kernel aumenta os buffers quando uma conexão se beneficia de mais espaço.
Seu trabalho é principalmente garantir que o teto não seja muito baixo. Se a taxa de transferência for ruim em uma rede longa e larga e ss -tin mostrar janelas de recebimento pequenas ou um remetente bloqueado pelo receptor, aumentar tcp_rmem, tcp_wmem, rmem_max e wmem_max pode ajudar.
Verifique as conexões ativas com:
ss -tin dst <ip-do-par>
Procure campos como cwnd, rtt, rto, bytes_acked, bytes_received e contadores de retransmissão. Eles contam uma história melhor do que um único teste de velocidade.
Controle de Congestionamento: CUBIC, BBR e Realidade
O algoritmo de controle de congestionamento decide como o TCP aumenta ou diminui sua taxa de envio. Em muitos sistemas Linux, o CUBIC é o padrão e funciona bem para tráfego geral de internet e datacenter. O BBR pode melhorar a taxa de transferência e a latência em alguns caminhos com perda ou longa distância porque modela a largura de banda do gargalo e o tempo de ida e volta em vez de reagir apenas à perda de pacotes.
Verifique os algoritmos disponíveis:
sysctl net.ipv4.tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control
Habilite o BBR apenas se seu kernel o tiver disponível:
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
Para persistência:
net.ipv4.tcp_congestion_control = bbr
Alguns sistemas também exigem o escalonador de pacotes de fila justa para um bom comportamento do BBR:
net.core.default_qdisc = fq
Não presuma que o BBR é sempre mais rápido. Ele pode alterar a justiça com outros fluxos, e diferentes versões do BBR se comportam de maneira diferente entre kernels. Teste-o no mesmo padrão de tráfego que você se importa: muitas chamadas de API pequenas, algumas transferências em massa, tráfego de banco de dados replicado ou carga mista semelhante à produção.
Filas de Escuta: Corrija Quedas Antes que se Tornem Mistérios
Problemas de taxa de transferência às vezes aparecem como falhas de conexão durante picos de tráfego. Se um serviço aceita novas conexões TCP mais lentamente do que os clientes as criam, as filas do kernel enchem.
Configurações relevantes:
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
somaxconn limita o backlog de conexão concluída solicitado pelos aplicativos através de listen(2). tcp_max_syn_backlog afeta a capacidade da fila SYN semiaberta. Aumentá-los pode ajudar servidores web ocupados, proxies e balanceadores de carga, mas o aplicativo também deve solicitar um backlog grande o suficiente. Nginx, HAProxy, Envoy e servidores de aplicativos geralmente têm suas próprias configurações de backlog.
Fique atento a estouros:
nstat -az | egrep 'ListenOverflows|ListenDrops|Syncookies'
ss -ltn
Se ListenOverflows aumentar, as filas do kernel não estão acompanhando. Se a CPU estiver saturada ou o aplicativo estiver bloqueado em serviços downstream, aumentar os tamanhos das filas pode reduzir os erros do cliente brevemente, mas não corrigirá o serviço.
Backlog e Processamento de Pacotes
net.core.netdev_max_backlog controla quantos pacotes podem esperar na fila de entrada quando o kernel recebe pacotes mais rápido do que pode processá-los.
net.core.netdev_max_backlog = 250000
Isso pode ajudar em interfaces de alta velocidade durante rajadas, especialmente com rede virtualizada. Também pode adicionar latência se você transformar o host em uma grande sala de espera de pacotes. Verifique primeiro as quedas na interface:
ip -s link show dev eth0
ethtool -S eth0 | egrep 'drop|err|timeout|miss|fifo'
Se as quedas no nível do driver estiverem aumentando, inspecione também os tamanhos dos anéis da NIC, a distribuição de interrupções, as filas RSS e a afinidade da CPU. Isso está fora do sysctl, mas geralmente é mais importante que os buffers TCP em hosts de 10 Gbps e mais rápidos.
TIME_WAIT e Exaustão de Portas
Clientes, proxies e executores de tarefas de alta taxa de transferência podem ficar sem portas efêmeras ou acumular muitos soquetes em TIME_WAIT. Tenha cuidado aqui porque conselhos antigos de ajuste podem ser prejudiciais.
Verifique o intervalo atual:
sysctl net.ipv4.ip_local_port_range
ss -tan state time-wait | wc -l
Um ajuste razoável do lado do cliente é ampliar o intervalo de portas efêmeras:
net.ipv4.ip_local_port_range = 10240 60999
Evite conselhos antigos que recomendam tcp_tw_recycle; ele foi removido do Linux porque quebrava o tráfego válido, especialmente atrás de NAT. tcp_tw_reuse existe em muitos kernels, mas seu comportamento mudou ao longo do tempo. Não o habilite como uma configuração de taxa de transferência padrão. Se você acha que precisa dele, teste seu kernel e padrão de tráfego exatos com cuidado.
Para servidores, uma pilha de soquetes TIME_WAIT geralmente é normal. Para clientes, a exaustão de portas geralmente significa que você precisa de pool de conexões, keep-alive, HTTP/2, menos conexões de saída de curta duração ou mais IPs de origem.
Um Arquivo Inicial Conservador
Aqui está um ponto de partida prático para um servidor de alta taxa de transferência. Ele não é intencionalmente extremo:
# /etc/sysctl.d/90-network-throughput.conf
# Tetos de ajuste automático TCP maiores para caminhos de alta largura de banda ou latência mais alta.
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 131072 33554432
net.ipv4.tcp_wmem = 4096 131072 33554432
# Filas maiores para tráfego de entrada em rajadas.
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 8192
net.core.netdev_max_backlog = 250000
# Opcional: teste antes de habilitar globalmente.
# net.core.default_qdisc = fq
# net.ipv4.tcp_congestion_control = bbr
Aplique:
sudo sysctl --system
Em seguida, meça novamente. Use o mesmo tamanho de teste, janela de tempo, número de fluxos paralelos e caminho de rede. Um teste de antes e depois que altera cinco variáveis não é evidência.
Erros Comuns
O primeiro erro é ajustar em um caminho com perda. O TCP vê a perda como congestionamento. Buffers maiores podem aumentar um pouco a taxa de transferência, mas também podem aumentar a latência e esconder o problema real. Corrija cabos ruins, switches virtuais sobrecarregados, policiamento de pacotes, incompatibilidade de MTU e caminhos VPN instáveis primeiro.
O segundo erro é presumir que iperf3 -P 8 prova o desempenho do aplicativo. Fluxos paralelos podem preencher um link mesmo quando uma única conexão de aplicativo real não consegue. Essa é uma informação útil, mas não é a história completa.
O terceiro erro é definir buffers enormes em hosts compartilhados. Tetos maiores são bons quando o kernel aumenta os buffers apenas conforme necessário, mas a pressão da memória muda tudo. Monitore free, slabtop, memória TCP e memória do aplicativo após as alterações.
O quarto erro é esquecer a reversão. Mantenha os valores anteriores em seu ticket de alteração ou 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 o sysctl Não é a Solução
Se um núcleo de CPU estiver no limite enquanto outros estão ociosos, olhe para o tratamento de interrupções, RSS, RPS/XPS e threading do aplicativo. Se a espera do disco for alta, a rede pode estar esperando o armazenamento. Se o TLS consumir CPU, teste com e sem criptografia e considere hardware, escolha de cifra ou reutilização de conexão. Se o Kubernetes ou um balanceador de carga de nuvem estiver no caminho, verifique os limites de nível de serviço e as tabelas conntrack.
Para hosts com uso intensivo de NAT, inspecione também o conntrack:
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
Isso não é ajuste de taxa de transferência TCP, mas a exaustão do conntrack pode parecer lentidão aleatória da rede ou conexões descartadas.
Testando Sem se Enganar
Use iperf3 como uma ferramenta de rede, não como prova de que o aplicativo está corrigido. Um teste de fluxo único é útil porque mostra o que uma única conexão TCP pode fazer:
iperf3 -c test-host -t 30
Um teste paralelo mostra se o link pode ser preenchido por vários fluxos:
iperf3 -c test-host -P 8 -t 30
Se os fluxos paralelos são rápidos, mas um fluxo é lento, olhe para o controle de congestionamento, crescimento da janela TCP, RTT e perda de pacotes. Se ambos são lentos, olhe mais abaixo: erros de interface, limites de largura de banda da nuvem, saturação da CPU, MTU, inspeção de firewall ou armazenamento por trás do remetente e receptor.
Mantenha o caminho de teste realista. Testar dois hosts no mesmo rack não lhe dirá muito sobre um trabalho de backup que cruza regiões. Testar com um arquivo minúsculo não exporá a taxa de transferência em estado estacionário. Testar através de uma VPN pode medir o appliance VPN mais do que o TCP Linux.
Após cada alteração, capture os mesmos contadores:
nstat -az > /tmp/nstat-after.txt
ss -s
sar -n DEV,TCP,ETCP 1 10
O resultado útil não é apenas "o número subiu". Você quer saber se as retransmissões caíram, as filas pararam de transbordar, a CPU permaneceu razoável e a latência não piorou para solicitações menores.
Uma boa otimização de rede Linux é medida e reversível. Aumente os tetos do buffer TCP quando o caminho precisar de janelas maiores. Teste o controle de congestionamento em vez de presumir que um algoritmo vence em todos os lugares. Aumente as filas de escuta quando vir quedas na fila e corrija o aplicativo se ele não conseguir aceitar rápido o suficiente. sysctl é útil, mas é uma camada em um sistema maior.