Base de conhecimento

Configurações de kernel para muitas conexões abertas

Os valores de sysctl e limites de systemd que importam quando uma máquina mantém dezenas de milhares de sockets, e os que foram copiados de posts antigos de blog e não fazem nada.

Meça antes

ss -s
cat /proc/sys/fs/file-nr
nstat -az TcpExtListenOverflows TcpExtListenDrops

ListenOverflows subindo significa que a fila de aceitação está cheia e o kernel está descartando handshakes concluídos. Isso é um problema específico com uma correção específica. A maioria dos outros sintomas não é resolvida por sysctl, e ajustar uma máquina que não está sob pressão só move a falha eventual para algum lugar mais difícil de encontrar.

As configurações que valem a pena

# /etc/sysctl.d/90-connections.conf
fs.file-max = 2097152
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 32768
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_mtu_probing = 1
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
sysctl --system
sysctl net.ipv4.tcp_congestion_control

O que cada uma faz:

  • somaxconn limita o backlog de escuta, e sua aplicação ainda precisa pedi-lo. No nginx, isso é listen ... backlog=65535; na maioria das linguagens, é o segundo argumento para listen().
  • ip_local_port_range importa no lado do cliente. Um proxy abrindo conexões de saída para um único destino esgota as portas efêmeras em cerca de vinte e oito mil com o intervalo padrão.
  • tcp_tw_reuse permite que o kernel reutilize sockets TIMEWAIT para novas conexões de saída. Seguro. Seu primo `tcptw_recycle` foi removido do Linux no 4.12, e qualquer guia que ainda o recomende foi escrito antes de 2017.
  • fq com bbr é uma melhoria real em caminhos longos ou com perdas e um empate em caminhos curtos e limpos. Ambos estão nos kernels padrão.

Rastreamento de conexões

Um firewall stateful dá a cada conexão uma entrada de conntrack, e a tabela tem um teto. Alcançá-lo descarta pacotes e escreve nf_conntrack: table full no log do kernel.

sysctl net.netfilter.nf_conntrack_max net.netfilter.nf_conntrack_count

Aumente se você tiver memória — cada entrada custa algumas centenas de bytes:

net.netfilter.nf_conntrack_max = 1048576

Onde a carga de trabalho é um serviço público sem estado, a melhor resposta é não rastrear:

table inet raw {
  chain prerouting {
    type filter hook prerouting priority raw;
    tcp dport 443 notrack
  }
}

Os limites que o systemd ignora

/etc/security/limits.conf se aplica a logins via PAM. Não tem efeito algum sobre um serviço iniciado pelo systemd, que é por isso que aumentar nofile ali e reiniciar o nginx não muda absolutamente nada. Defina-o na unit:

mkdir -p /etc/systemd/system/nginx.service.d
cat > /etc/systemd/system/nginx.service.d/limits.conf <<EOF
[Service]
LimitNOFILE=1048576
EOF
systemctl daemon-reload
systemctl restart nginx

Verifique contra o serviço em execução em vez do arquivo que você acabou de escrever:

systemctl show nginx -p LimitNOFILE

Três coisas para não fazer

  • Não cole um arquivo sysctl de cinquenta linhas de um fórum. Metade dele visa um kernel que não é lançado há uma década, e uma linha vai silenciosamente quebrar a descoberta de MTU de caminho.
  • Não aumente tcp_rmem e tcp_wmem sem um caminho longo e gordo para justificar. Em um caminho de um milissegundo, buffers maiores compram latência e pressão de memória.
  • Não desative tcp_timestamps. Você perde a estimativa de ida e volta e PAWS, e ganha um boato sobre desempenho.

Meça novamente após cada mudança, uma mudança de cada vez, e mantenha o arquivo no controle de versão para que a próxima pessoa possa ver o que você fez e por quê.

Pronto quando você estiver

Escolha uma cidade. Escolha um tamanho. Pague em cripto.

Sem formulários sobre quem você é, sem esperar aprovação de um humano, sem ligação para verificar nada. O pagamento é confirmado e as credenciais chegam na sua caixa de entrada.