Come sono state decise queste impostazioni predefinite di TCP TCP?


13

Ho trascorso un po 'di tempo a rintracciare un problema nella produzione di recente, in cui un server database scomparendo avrebbe causato un blocco fino a 2 ore (lunga attesa per una poll()chiamata nella libreria client libpq) per un client connesso. Scavando nel problema, mi sono reso conto che questi parametri del kernel dovrebbero essere regolati in modo da poter rilevare tempestivamente le connessioni TCP interrotte:

net.ipv4.tcp_keepalive_time = 7200 net.ipv4.tcp_keepalive_probes = 9 net.ipv4.tcp_keepalive_intvl = 75 net.ipv4.tcp_retries2 = 15

I quattro valori sopra riportati provengono da una macchina Ubuntu 12.04 e sembra che questi valori predefiniti siano invariati rispetto ai valori predefiniti del kernel Linux corrente .

Queste impostazioni sembrano essere fortemente distorte nel mantenere aperta una connessione esistente e nell'essere estremamente avari di sonde keepalive. AIUI, il valore predefinito tcp_keepalive_timedi 2 ore significa che quando stiamo aspettando una risposta per un host remoto, aspetteremo pazientemente 2 ore prima di avviare un probe keepalive per verificare che la nostra connessione sia ancora valida. E quindi, se l'host remoto non risponde a una sonda keepalive, riproviamo quelle sonde keepalive 9 volte ( tcp_keepalive_probes), distanziate di 75 secondi ( tcp_keepalive_intvl), quindi sono altri 11 minuti prima di decidere che la connessione è davvero interrotta.

Questo corrisponde a quello che ho visto sul campo: ad esempio, se avvio una psqlsessione connessa a un'istanza PostgreSQL remota, con qualche query in attesa di una risposta, ad es.

SELECT pg_sleep(30);

e poi il server remoto muore in modo orribile (ad esempio, rilascia il traffico su quella macchina), vedo la mia sessione psql attendere fino a 2 ore e 11 minuti prima di scoprire che la sua connessione è interrotta. Come puoi immaginare, queste impostazioni predefinite causano seri problemi al codice di cui stiamo parlando con un database durante, ad esempio, un evento di failover del database. Abbassare queste manopole ha aiutato molto! E vedo che non sono il solo a consigliare queste impostazioni predefinite.

Quindi le mie domande sono:

  • Da quanto tempo le impostazioni predefinite sono state così?
  • Qual è stata la logica originale per rendere predefinite queste impostazioni TCP?
  • Le distro Linux cambiano questi valori predefiniti?

E qualsiasi altra storia o prospettiva sulla logica di queste impostazioni sarebbe apprezzata.



Si noti che è possibile modificare le prime tre per-connessione in codice client con le opzioni di socket TCP_KEEPIDLE, TCP_KEEPCNTe TCP_KEEPINTVL.
wnoise,

1
@wnoise in realtà da Linux 2.6.37 dovrebbe anche essere possibile specificare l'opzione socket TCP_USER_TIMEOUT, invece di impostare a livello di net.ipv4.tcp_retries2sistema. Naturalmente molte applicazioni (come PostgreSQL nel mio esempio qui) non supportano TCP_USER_TIMEOUTancora.
Josh Kupershmidt,

Risposte:


6

RFC 1122 specifica nella sezione 4.2.3.6 che il periodo di mantenimento non deve essere inferiore a due ore.


1
Bene, grazie per averlo scoperto. Penso che principalmente risponda alla domanda sul perché l' tcp_keepalive_timeimpostazione predefinita è 7200, anche se sarei comunque interessato al precedente / spiegazione per le altre tre impostazioni pertinenti.
Josh Kupershmidt,

Rimozione della mia risposta poiché risponde alla domanda (almeno per uno dei valori)
coteyr

1
@coteyr Grazie comunque, apprezzo lo sforzo. IIRC c'era un commento interessante sulla tua risposta che suggeriva che nei kernel precedenti di Linux il valore predefinito era di 15 minuti. Sarei interessato a come / perché questo è stato modificato in 2 ore o impostato su 15 minuti in primo luogo.
Josh Kupershmidt,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.