Base di conoscenza

Impostazioni del kernel per un gran numero di connessioni aperte

I valori sysctl e i limiti di systemd che contano quando una macchina tiene decine di migliaia di socket, e quelli copiati da vecchi post di blog che non fanno nulla.

Misurare prima

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

ListenOverflows in salita significa che la coda di accettazione è piena e il kernel sta scartando handshake completati. È un problema specifico con una soluzione specifica. La maggior parte degli altri sintomi non si risolve affatto con sysctl, e ottimizzare una macchina che non è sotto pressione sposta semplicemente il guasto finale in un punto più difficile da trovare.

Le impostazioni che meritano il loro posto

# /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

Cosa fa ciascuna:

  • somaxconn limita il listen backlog, e la tua applicazione deve comunque richiederlo. In nginx è listen ... backlog=65535; nella maggior parte dei linguaggi è il secondo argomento di listen().
  • ip_local_port_range conta sul lato client. Un proxy che apre connessioni in uscita verso una sola destinazione esaurisce le porte effimere a circa ventottomila con l'intervallo predefinito.
  • tcp_tw_reuse consente al kernel di riutilizzare i socket TIMEWAIT per nuove connessioni in uscita. Sicura. Sua cugina `tcptw_recycle` è stata rimossa da Linux in 4.12, e qualsiasi guida che la raccomandi ancora è stata scritta prima del 2017.
  • fq con bbr è un vero miglioramento su percorsi lunghi o con perdite, e un lavaggio su percorsi brevi e puliti. Entrambi sono nei kernel standard.

Connection tracking

Un firewall stateful dà a ogni connessione una voce conntrack, e la tabella ha un tetto. Raggiungerlo scarta i pacchetti e scrive nf_conntrack: table full nel log del kernel.

sysctl net.netfilter.nf_conntrack_max net.netfilter.nf_conntrack_count

Alzalo se hai memoria — ogni voce costa qualche centinaio di byte:

net.netfilter.nf_conntrack_max = 1048576

Dove il carico di lavoro è un servizio pubblico senza stato, la risposta migliore è non tracciarlo:

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

I limiti che systemd ignora

/etc/security/limits.conf si applica ai login tramite PAM. Non ha alcun effetto su un servizio avviato da systemd, motivo per cui alzare nofile lì e riavviare nginx non cambia assolutamente nulla. Impostalo sulla 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

Verifica con il servizio in esecuzione piuttosto che con il file che hai appena scritto:

systemctl show nginx -p LimitNOFILE

Tre cose da non fare

  • Non incollare un file sysctl di cinquanta righe da un forum. Metà di esso riguarda un kernel che non viene più distribuito da un decennio, e una riga romperà silenziosamente il path MTU discovery.
  • Non alzare tcp_rmem e tcp_wmem senza un percorso lungo e largo che lo giustifichi. Su un percorso da un millisecondo, buffer più grandi comprano latenza e pressione sulla memoria.
  • Non disabilitare tcp_timestamps. Perdi la stima del round-trip e PAWS, e guadagni una voce sulla performance.

Misura di nuovo dopo ogni modifica, una modifica alla volta, e tieni il file sotto controllo di versione così la prossima persona può vedere cosa hai fatto e perché.

Pronto quando lo sei

Scegli una città. Scegli una dimensione. Paga in criptovaluta.

Nessun modulo su chi sei, nessuna attesa per l'approvazione di una persona, nessuna chiamata per verificare nulla. La fattura viene saldata e le credenziali arrivano nella tua casella di posta.