pgBouncer ใช้งานได้ดี แต่บางครั้งก็ใช้งานไม่ได้


9

ฉันกำลังเรียกใช้ pgBouncer หน้าฐานข้อมูล postgres 9 ที่ไม่ว่าง สำหรับส่วนใหญ่เวลาทำงานได้ดี แต่ทุก ๆ สองสามชั่วโมงฉันจะได้รับอีเมลข้อผิดพลาดจากแอปพลิเคชันของฉันโดยมีข้อยกเว้นจาก psycopg2:

OperationalError ('ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์: ไม่สามารถกำหนดที่อยู่ที่ร้องขอเซิร์ฟเวอร์ทำงานบนโฮสต์ "neo-hulk" และยอมรับการเชื่อมต่อ TCP / IP บนพอร์ต 6432 หรือไม่')

แอพนี้เป็นแอพที่มีคนทำงานคื่นฉ่ายหลายคนกำลังทำงานอยู่ เมื่อข้อผิดพลาดเหล่านั้นมาถึงฉันจะตรวจสอบ pgbouncer db และขนาดพูลอยู่ในขีด จำกัด หลังจากการทดลองบางอย่างฉันได้ตั้งค่าขนาดสูงสุดของพูลเป็น 400 และขนาดพูลเป็น 200 โหมดพูคือ "เซสชัน" (คำขอส่วนใหญ่จะกระทำโดยอัตโนมัติเกือบจะไม่มีธุรกรรม)

อะไรทำให้ pgBouncer 'หายไป' อย่างนั้น? เป็นเพียงช่วงเวลาสั้น ๆ เท่านั้น (และโดยรวมแล้วเรากำลังพูดถึงคำขอจำนวนเล็กน้อยเมื่อเทียบกับปริมาณคำขอที่แท้จริงที่มอบให้) แต่คำขอที่ล้มเหลวนั้นมีความสำคัญ

ขอบคุณ!


ระบบปฏิบัติการและเวอร์ชั่น? รุ่นเคอร์เนลถ้า Linux? รุ่น PostgreSQL ที่แน่นอนและ PgBouncer ใช่ไหม คุณรัน PgBouncer ในระดับบันทึกการดีบั๊กแล้วดูว่ารายงานสิ่งใดมีประโยชน์หรือไม่
Craig Ringer

Debian 6. Linux เวอร์ชัน 2.6.32-5-amd64 (Debian 2.6.32-48squeeze1) pgbouncer เวอร์ชั่น 1.5.4 Postgres 9.1 บันทึกไม่ได้ล็อกการเชื่อมต่อ / ตัดการเชื่อมต่อเนื่องจากฉันคิดว่ามันค่อนข้างมาก แต่ไม่มีข้อผิดพลาดเกิดขึ้นเมื่อโยนข้อผิดพลาดของแอปเหล่านั้น ข้อผิดพลาดมาจาก psycopg2 คิดว่าไม่มีเซิร์ฟเวอร์ db ที่จะพูดคุยถึงแม้ว่าปัญหานี้ไม่ได้มีอยู่ก่อน pgbouncer
Harel

1
หืม PgBouncer ปัจจุบันและเคอร์เนลนั้นโบราณ แต่ค่อนข้างเสถียร ฉันคิดว่าคุณต้องเปิดใช้งานการบันทึกรายละเอียดเพิ่มเติมใน PgBouncer ด้วย-vvvและดูว่าคุณสามารถจับคู่เอาต์พุตบันทึกที่ผิดปกติกับข้อผิดพลาดของคุณในเวลาหรือไม่
Craig Ringer

ฉันทำ "set verbose = 1; reload;" ใน pgbouncer shell และไม่พบสิ่งผิดปกติในบันทึก นี่เป็นระบบที่ใช้งานจริงดังนั้นจึงไม่สามารถหยุดให้บริการทำงานในรูปแบบที่ไม่ใช่ภูตด้วย -vvv หวังว่าฉันจะได้ผลลัพธ์เดียวกัน โปรดทราบว่าข้อผิดพลาดแสดงว่าไม่สามารถเชื่อมต่อกับ pgbouncer ได้เลยนั่นคือไม่พบว่ากำลังฟังอยู่ในพอร์ตนั้น มีการเชื่อมต่อหลายพันครั้งที่เกิดขึ้นตลอดเวลาและมีความแปลกที่ว่ามีการเชื่อมต่อจำนวนน้อยล้มเหลวเช่นนั้น
Harel

หากิน; ดูเหมือนสภาพการแข่งขันที่มีศักยภาพ แต่ในสิ่งที่ / ที่ ...
เครก Ringer

คำตอบ:


15

ส่วน " ไม่สามารถกำหนดที่อยู่ที่ร้องขอ " ในข้อความแสดงข้อผิดพลาดมาจากสแต็ค TCP เคอร์เนล เมื่อพบเป็นระยะ ๆ โดยทั่วไปหมายความว่าพื้นที่ของซ็อกเก็ตที่มีอยู่หมดเนื่องจากซ็อกเก็ตมากเกินไปในสถานะรอ ( TIME_WAITหรืออาจน้อยกว่าFIN_WAIT_1หรือFIN_WAIT_2)

cat /proc/sys/net/ipv4/ip_local_port_rangeช่วงของพอร์ตซ็อกเก็ตสามารถส่งออกโดย 32768 61000ค่าเริ่มต้นในหุ้นเคอร์เนลโดยทั่วไป

คุณสามารถตรวจสอบผลลัพธ์ของnetstat -ton|grep WAITลูกค้าและโฮสต์ของ pgBouncer เมื่อระบบไม่ว่าง -oธงจะแสดงเคาน์เตอร์หมดเวลาที่เกี่ยวข้องกับรัฐรอ

หากจำนวนซ็อกเก็ต TCP ทั้งหมดใกล้เคียง61000-32768=28232แล้วการหมดช่วงนี้น่าจะเป็นปัญหาของคุณ เนื่องจากซ็อกเก็ตปิดใช้เวลา 60 วินาทีในTIME_WAITสถานะปกติหากโฮสต์ไคลเอ็นต์เชื่อมต่อมากกว่า 28232 ครั้งในหนึ่งนาทีการเชื่อมต่อใหม่จะล้มเหลวพร้อมกับข้อผิดพลาดที่กล่าวถึงจนกว่าพอร์ตจะว่าง

เป็นวิธีแก้ปัญหาแรกช่วงพอร์ต TCP อาจถูกขยาย:

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

ถ้ามันไม่ได้เป็นที่น่าพอใจให้ตรวจสอบtcp_tw_recycleและtcp_tw_reuseธงยังพริ้งผ่านและ/proc/sys/net/ipv4sysctl

พวกเขาถูกกำหนดให้เป็น (จากman tcp):

       tcp_tw_recycle (Boolean; default: disabled; เนื่องจาก Linux 2.4)
              เปิดใช้งานการรีไซเคิลอย่างรวดเร็วของซ็อกเก็ต TIME_WAIT เปิดใช้งานสิ่งนี้
              ไม่แนะนำให้ใช้ตัวเลือกเนื่องจากจะทำให้เกิดปัญหาเมื่อทำงาน ‐
              ไอเอ็นจีกับ NAT (แปลที่อยู่เครือข่าย)

       tcp_tw_reuse (บูลีนค่าเริ่มต้น: ปิดใช้งานตั้งแต่ Linux 2.4.19 / 2.6)
              อนุญาตให้ใช้ซ็อกเก็ต TIME_WAIT ซ้ำสำหรับการเชื่อมต่อใหม่เมื่อเป็น
              ปลอดภัยจากมุมมองโปรโตคอล ไม่ควรเปลี่ยนแปลงหากไม่มี
              คำแนะนำ / คำขอของผู้เชี่ยวชาญด้านเทคนิค

โดยส่วนตัวแล้วฉันประสบความสำเร็จtcp_tw_recycleเมื่อต้องเผชิญกับปัญหานี้ด้วยแอปไคลเอนต์ MySQL แต่ไม่ได้ทำตามคำแนะนำความเข้าใจของฉันเกี่ยวกับ TCP นั้นเป็นเรื่องที่ดีที่สุด


1
คำตอบนั้นแสดงให้เห็นถึงข้อผิดพลาดอะไรก็ตามที่เข้าใจ TCP ขอบคุณสำหรับสิ่งนั้น. ฉันได้เพิ่มช่วงพอร์ตและปล่อยให้มันทำงานชั่วขณะหนึ่งเพื่อดูว่ามันมีผลกระทบหรือไม่ (ฉันจำเป็นต้องรีบูตเครื่องหลังจากตั้งค่าหรือไม่?)
Harel

ฉันคิดว่าการเพิ่มพอร์ตได้ทำไปแล้ว จนถึงตอนนี้ฉันยังไม่ได้รับข้อผิดพลาดใด ๆ จำนวนคร่าวๆของบรรทัด netstat แสดงให้เห็นใกล้เคียงกับ 20K ในไคลเอนต์ดังนั้นจากนั้นถึงขีด จำกัด เริ่มต้นที่ 28K ไม่นาน ขอบคุณสำหรับสิ่งนั้น!
Harel

1
ดี! คุณต้องการตั้งค่า/etc/sysctl.confตามที่net.ipv4.ip_local_port_range = 1025 65535จะให้มันคงอยู่ในการรีบูต
Daniel Vérité

ขอบคุณ ฉันได้รับข้อผิดพลาดตั้งแต่ แต่ไม่ใช่อันนั้นยังดีอยู่ ปล่อยให้มันรันไปสองสามวันและจะเปลี่ยนใบอนุญาต ฉันดีใจที่นี้เพื่อให้ห่างไกลดูเหมือนว่าจะทำงานเพราะการเปลี่ยนแปลงอื่น ๆ หลอนฉัน :)
Harel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.