pgBouncer berfungsi dengan baik tetapi terkadang menjadi tidak tersedia

9

Saya menjalankan pgBouncer di depan database postgres 9 yang sibuk. Untuk sebagian besar waktu itu berfungsi dengan baik. Tetapi setiap beberapa jam saya akan mendapatkan email kesalahan dari aplikasi saya dengan pengecualian dari psycopg2:

OperationalError ('tidak dapat terhubung ke server: Tidak dapat menetapkan alamat yang diminta Apakah server berjalan pada host "neo-hulk" dan menerima koneksi TCP / IP pada port 6432?')

Ini adalah aplikasi python dengan sekelompok pekerja seledri yang menjalankan tugas. Ketika kesalahan-kesalahan itu tiba, saya memeriksa pgbouncer db dan ukuran kumpulan masih dalam batas. Setelah beberapa percobaan, saya telah mengatur ukuran max kolam ke 400 dan ukuran pool ke 200. Mode pool adalah "sesi" (sebagian besar permintaan komit otomatis, hampir tidak ada transaksi).

Apa yang membuat pgBuncer 'menghilang' seperti itu? ini hanya untuk periode waktu yang singkat (dan secara total kita berbicara tentang sejumlah kecil permintaan dibandingkan dengan volume permintaan yang diberikannya) tetapi permintaan yang gagal itu penting.

Terima kasih!

Harel
sumber
Sistem operasi dan versi? Versi kernel jika Linux? Versi PostgreSQL dan PgBouncer yang tepat? Sudahkah Anda menjalankan PgBouncer di tingkat log debug dan melihat apakah laporan itu bermanfaat?
Craig Ringer
Debian 6. Linux versi 2.6.32-5-amd64 (Debian 2.6.32-48squeeze1) pgbouncer versi 1.5.4 Postgres 9.1. Log tidak terhubung / terputus karena saya pikir itu agak banyak, tetapi tidak ada kesalahan saat kesalahan aplikasi dilemparkan. Kesalahan berasal dari psycopg2 berpikir tidak ada server db untuk diajak bicara, meskipun masalah ini tidak ada pra pgbouncer
Harel
1
Hm, jadi PgBouncer saat ini, dan kernelnya kuno tapi cukup stabil. Saya pikir Anda perlu mengaktifkan logging lebih detail di PgBouncer dengan -vvvdan melihat apakah Anda dapat mencocokkan keluaran log yang aneh dengan kesalahan Anda dalam waktu.
Craig Ringer
Saya melakukan "set verbose = 1; reload;" di shell pgbouncer dan tidak dapat menemukan sesuatu yang luar biasa di log. ini adalah sistem produksi sehingga tidak dapat menghentikan layanan untuk berjalan sebagai non daemon dengan -vvv. Semoga saya mendapat hasil yang sama. perhatikan bahwa kesalahan menunjukkan bahwa ia tidak dapat terhubung ke pgbouncer sama sekali, yaitu, tidak dapat menemukannya mendengarkan di port itu. Ada ribuan koneksi yang dibuat sepanjang waktu dan aneh bahwa sejumlah kecil dari mereka gagal seperti itu.
Harel
Rumit; kedengarannya seperti kondisi lomba yang potensial, tetapi dalam apa / di mana ...
Craig Ringer

Jawaban:

15

Bagian " Tidak dapat menetapkan alamat yang diminta " dalam pesan kesalahan berasal dari tumpukan TCP kernel. Ketika ditemui sesekali, ini biasanya berarti bahwa ruang soket yang tersedia habis karena terlalu banyak soket dalam keadaan menunggu ( TIME_WAIT, atau kurang mungkin FIN_WAIT_1atau FIN_WAIT_2)

Kisaran port soket dapat dihasilkan oleh cat /proc/sys/net/ipv4/ip_local_port_range. Nilai default pada kernel Linux stock umumnya 32768 61000.

Anda dapat memeriksa hasil netstat -ton|grep WAITpada klien dan host pgBuncer ketika sistem sedang sibuk. The -obendera akan menunjukkan counter batas waktu yang terkait dengan negara menunggu.

Jika jumlah total soket TCP dekat dengan itu 61000-32768=28232maka kelelahan rentang ini kemungkinan menjadi masalah Anda. Karena soket tertutup menghabiskan 60 detik dalam TIME_WAITkondisi normal, jika host klien menghubungkan lebih dari 28232 kali dalam satu menit, koneksi baru akan gagal dengan kesalahan yang disebutkan sampai port dibebaskan.

Sebagai solusi pertama, rentang port TCP dapat diperpanjang:

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

Jika tidak memuaskan, periksa tcp_tw_recycledan tcp_tw_reuseberi tanda, juga bisa dicari melalui /proc/sys/net/ipv4dan sysctl.

Mereka didefinisikan sebagai (dari man tcp):

       tcp_tw_recycle (Boolean; default: dinonaktifkan; sejak Linux 2.4)
              Aktifkan daur ulang cepat soket TIME_WAIT. Mengaktifkan ini
              opsi tidak direkomendasikan karena ini menyebabkan masalah ketika bekerja -
              dengan NAT (Terjemahan Alamat Jaringan).

       tcp_tw_reuse (Boolean; default: dinonaktifkan; sejak Linux 2.4.19 / 2.6)
              Izinkan untuk menggunakan kembali soket TIME_WAIT untuk koneksi baru saat itu
              aman dari sudut pandang protokol. Seharusnya tidak diubah tanpa
              saran / permintaan ahli teknis.

Secara pribadi saya berhasil tcp_tw_recycleketika dihadapkan dengan masalah ini dengan aplikasi klien MySQL, tetapi jangan menganggap ini sebagai rekomendasi, pemahaman saya tentang TCP menjadi dangkal.

Daniel Vérité
sumber
1
Jawaban itu menunjukkan bug apa pun pemahaman dangkal TCP. Terima kasih untuk itu. Saya telah meningkatkan jangkauan port dan membiarkannya berjalan untuk sementara waktu untuk melihat apakah ada efeknya. (Apakah saya perlu reboot setelah saya mengaturnya?)
Harel
Saya pikir peningkatan port telah melakukannya. Sejauh ini saya belum menerima kesalahan. Hitungan kasar dari garis netstat menunjukkan hampir 20K di klien sehingga dari sana ke batas default 28K tidak panjang. Terima kasih untuk itu!
Harel
1
Baik! Anda ingin menempatkan pengaturan dalam /etc/sysctl.confkarena net.ipv4.ip_local_port_range = 1025 65535untuk memilikinya bertahan di reboot.
Daniel Vérité
Terima kasih. Saya telah menerima kesalahan sejak itu tetapi tidak yang salah sehingga masih bagus. Membiarkannya berjalan selama beberapa hari dan akan membuat perm berubah. Saya senang sejauh ini tampaknya berhasil karena perubahan lainnya membuat saya takut :)
Harel