هذا المقال يتطلب مستوى متوسط. لو تعاملت قبل كده مع قاعدة بيانات وربطتها بتطبيق ويب، هتكون قادر تنفّذ كل خطوة هنا.
لو تطبيقك بيرمي FATAL: sorry, too many clients already وقت الذروة والـ CPU والرام مرتاحين، المشكلة مش في السيرفر. المشكلة إن كل اتصال بيفتح عملية كاملة في Postgres، والعمليات دي خلصت. الحل هو مجمّع اتصالات اسمه PgBouncer، وهتقدر تركّبه وتضبطه في أقل من 10 دقايق.
المشكلة باختصار
Postgres بيتعامل مع كل اتصال بموديل عملية-لكل-اتصال (process per connection). يعني كل client بيفتح اتصال، السيرفر بيعمل له عملية نظام تشغيل مستقلة، بتاخد ذاكرة ثابتة حتى وهي قاعدة مش بتعمل حاجة. لما تطبيقك يتوسّع ويفتح مئات الاتصالات المتزامنة، بتوصل لسقف max_connections بسرعة، وأي اتصال جديد بيترفض.
خلّينا نفهمها بمثال بسيط الأول
تخيّل مطعم فيه 20 طاولة بس. لو كل زبون دخل احتجز طاولة كاملة وقعد عليها طول الوقت — حتى وهو بيتكلم في التليفون ومش بياكل — الطاولات هتخلص بسرعة، وأي زبون جديد هيتقفل في وشه الباب. لكن المطعم الذكي بيخلّي في مضيف على الباب: الزباين يستنوا شوية، وأول ما طاولة تفضى، حد ياخدها، ياكل بسرعة، ويقوم. نفس الـ 20 طاولة بتخدم 600 زبون في الساعة.
PgBouncer هو المضيف ده. بدل ما كل طلب من تطبيقك يحجز "طاولة" (اتصال Postgres) لنفسه ويقعد عليها، PgBouncer بيمسك عدد صغير من الاتصالات الحقيقية ويوزّعها على مئات الطلبات. الطلب بياخد اتصال، ينفّذ الـ query، ويرجّعه فورًا لغيره.
الشرح العلمي الدقيق
PgBouncer هو connection pooler خفيف بيقعد بين تطبيقك وبين Postgres. بيدعم ثلاث أنماط تجميع: session، transaction، statement. الأكثر فائدة للتطبيقات الويب هو transaction pooling: الاتصال الحقيقي بيرجع للـ pool بمجرد انتهاء كل transaction، مش بعد ما الـ client يقفل. النتيجة إن 600 اتصال من التطبيق ممكن يتخدموا بـ 20 اتصال حقيقي بس على قاعدة البيانات.
الافتراض هنا إن طلباتك قصيرة (أقل من 100 مللي ثانية للـ query الواحد) وما بتفضلش ماسكة الاتصال طويلًا. ده الحال الشائع في REST APIs وتطبيقات الويب.
الحل خطوة بخطوة
- ركّب PgBouncer على نفس سيرفر التطبيق أو سيرفر مستقل قريب من الداتابيز.
- اكتب ملف الإعداد
pgbouncer.ini. - حدّد مستخدمي الاتصال في
userlist.txt. - وجّه تطبيقك على منفذ PgBouncer (6432) بدل منفذ Postgres (5432).
التركيب على Ubuntu/Debian:
# التركيب
sudo apt-get update && sudo apt-get install -y pgbouncer
# تشغيل الخدمة
sudo systemctl enable --now pgbouncerملف /etc/pgbouncer/pgbouncer.ini: