pgBouncer funziona alla grande ma a volte diventa non disponibile


9

Sto eseguendo pgBouncer davanti a un database postgres 9 occupato. Per la maggior parte del tempo funziona bene. Ma ogni poche ore riceverò un'e-mail di errore dalla mia applicazione con un'eccezione da psycopg2:

OperationalError ('impossibile connettersi al server: impossibile assegnare l'indirizzo richiesto Il server è in esecuzione sull'host "neo-hulk" e accetta connessioni TCP / IP sulla porta 6432?')

Questa è un'app Python con un gruppo di sedano che eseguono attività. Quando arrivano questi errori, controllo il db pgbouncer e la dimensione del pool è nei limiti. Dopo un po 'di sperimentazione ho impostato la dimensione massima del pool su 400 e la dimensione del pool su 200. La modalità pool è "sessione" (le richieste sono per lo più auto-commit, quasi nessuna transazione).

Cosa rende 'svanire' così pgBouncer? è solo per brevi periodi di tempo (e in totale stiamo parlando di una piccola quantità di richieste rispetto al semplice volume di richieste che gestisce) ma quelle richieste che falliscono sono importanti.

Grazie!


Sistema operativo e versione? Versione del kernel se Linux? Esatte versioni di PostgreSQL e PgBouncer? Hai eseguito PgBouncer a livello di registro di debug e hai visto se riporta qualcosa di utile?
Craig Ringer,

Debian 6. Linux versione 2.6.32-5-amd64 (Debian 2.6.32-48squeeze1) pgbouncer versione 1.5.4 Postgres 9.1. Il registro non registra la connessione / disconnessione poiché pensavo fosse un po 'troppo, ma non sono presenti errori quando vengono generati quegli errori dell'app. L'errore viene da psycopg2 pensando che non c'è un server db con cui parlare, anche se questo problema non esisteva pre pgbouncer
Harel,

1
Hm, quindi attuale PgBouncer, e il kernel è antico ma abbastanza stabile. Penso che sia necessario abilitare la registrazione più dettagliata in PgBouncer -vvve vedere se è possibile abbinare l'output anomalo del registro agli errori nel tempo.
Craig Ringer,

Ho fatto un "set verbose = 1; ricaricare;" nella shell pgbouncer e non è stato possibile trovare nulla di straordinario nel registro. questo è un sistema di produzione, quindi non è stato possibile interrompere l'esecuzione del servizio come non daemon con -vvv. Spero di avere lo stesso risultato. si noti che l'errore suggerisce che non è stato possibile connettersi a pgbouncer, ovvero che non è riuscito a trovarlo in ascolto in quella porta. Ci sono migliaia di connessioni fatte continuamente ed è strano che un piccolo numero di esse fallisca in quel modo.
Harel,

Difficile; sembra una potenziale condizione di gara, ma in cosa / dove ...
Craig Ringer,

Risposte:


15

La parte " Impossibile assegnare l'indirizzo richiesto " nel messaggio di errore proviene dallo stack TCP del kernel. Se rilevato in modo intermittente, ciò significa in genere che lo spazio dei socket disponibili è esaurito a causa di troppi socket nello stato di attesa ( TIME_WAIT, o meno probabilmente FIN_WAIT_1o FIN_WAIT_2)

La gamma di porte socket può essere emessa da cat /proc/sys/net/ipv4/ip_local_port_range. Il valore predefinito su un kernel Linux standard è generalmente 32768 61000.

È possibile verificare il risultato netstat -ton|grep WAITsul client (s) e sull'host pgBouncer quando il sistema è occupato. La -obandiera mostrerà i contatori di timeout relativi agli stati di attesa.

Se il numero totale di socket TCP è vicino, 61000-32768=28232allora l'esaurimento di questo intervallo è probabilmente il tuo problema. Poiché un socket chiuso trascorre 60 secondi nello TIME_WAITstato in condizioni normali, se un host client si connette più di 28232 volte in un minuto, le nuove connessioni non riusciranno con l'errore indicato fino a quando le porte non vengono liberate.

Come prima soluzione alternativa, l'intervallo di porte TCP può essere esteso:

 # echo "1025 65535" >/proc/sys/net/ipv4/ip_local_port_range

Se non è soddisfacente, controllare i flag tcp_tw_recyclee tcp_tw_reuse, anch'essi regolabili tramite /proc/sys/net/ipv4e sysctl.

Sono definiti come (da man tcp):

       tcp_tw_recycle (Booleano; impostazione predefinita: disabilitato; da Linux 2.4)
              Abilita il riciclaggio rapido dei socket TIME_WAIT. Abilitando questo
              l'opzione non è consigliata poiché causa problemi quando si lavora
              ing con NAT (Network Address Translation).

       tcp_tw_reuse (Booleano; impostazione predefinita: disabilitato; da Linux 2.4.19 / 2.6)
              Consentire di riutilizzare i socket TIME_WAIT per le nuove connessioni quando lo è
              sicuro dal punto di vista del protocollo. Non dovrebbe essere cambiato senza
              consulenza / richiesta di esperti tecnici.

Personalmente ho avuto successo di tcp_tw_recyclefronte a questo problema con un'app client MySQL, ma non prenderlo come una raccomandazione, la mia comprensione del TCP è al massimo superficiale.


1
Questa risposta mostra qualcosa che non comprende la comprensione superficiale di TCP. Grazie per questo. Ho aumentato l'intervallo di porte e l'ho lasciato funzionare per un po 'per vedere se ha qualche effetto. (Devo riavviare dopo averlo impostato?)
Harel,

Penso che l'aumento del porto lo abbia fatto. Finora non ho ricevuto alcun errore. Un conteggio approssimativo delle linee netstat mostra quasi 20K nel client, quindi da lì al limite predefinito di 28K non è lungo. Grazie per quello!
Harel,

1
Buona! Volete mettere l'impostazione in /etc/sysctl.confquanto net.ipv4.ip_local_port_range = 1025 65535per averlo persistono dopo il riavvio.
Daniel Vérité,

Grazie. Ho ricevuto errori da allora ma non quello, quindi è ancora buono. Lasciarlo funzionare per alcuni giorni e cambierà il perm. Sono contento che finora sembra funzionare perché gli altri cambiamenti mi spaventano :)
Harel,
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.