لو السيرفر بتاعك بيرمي خطأ FATAL: too many connections for role وانت لسه عند 800 مستخدم متزامن فقط، PostgreSQL مش بطيء — انت بتفتح اتصال جديد لكل request. PgBouncer في 12 سطر إعداد بيختصر 800 اتصال إنتاج لـ 25 اتصال فعلي على PostgreSQL، بدون تعديل سطر في تطبيقك.
PgBouncer للمتوسط: حل آلام الاتصالات في PostgreSQL بدون لمس الكود
المشكلة باختصار
كل اتصال PostgreSQL بياخد عملية process مستقلة في الذاكرة، حوالي 9MB إلى 14MB لكل واحد. لو عندك 4 instances من تطبيق Node.js، كل واحد بـ pool فيه 100 اتصال، يبقى DB قدامها 400 process بياكل تقريبًا 5.6GB RAM فاضي. زود traffic فجأة، ولاقي PostgreSQL بيرفض الاتصال 401 بـ too many connections.
الافتراض اللي بتغفل عنه: ORM زي Prisma أو SQLAlchemy بيفتح pool محلي على كل instance، بس مفيش أي طبقة تجمّع كل الـ pools دي قدام الـ DB.
المثال البسيط: شباك البنك
تخيل بنك فيه شباك واحد بيخدم زبون في الدقيقة. لو 200 زبون فتحوا الباب في نفس اللحظة، 199 بيقفوا في الشمس. الحل مش إن البنك يفتح 200 شباك — ده مكلف ومش هيشتغل. الحل إن في موظف استقبال واحد بيستقبل الـ 200 زبون، وبيدخّل لشباك واحد كل واحد على دور.
الموظف ده هو PgBouncer. الزبون هو الـ HTTP request في تطبيقك. والشباك هو الاتصال الفعلي على PostgreSQL.
التعريف العلمي
PgBouncer هو connection pooler خفيف بيتكلم بروتوكول PostgreSQL wire protocol. بيقعد بين التطبيق والـ DB، ويحتفظ بعدد ثابت صغير من الاتصالات الحقيقية. لما تطبيقك يطلب اتصال، PgBouncer بيديله "اتصال افتراضي" يبدو وكأنه PostgreSQL، لكنه فعليًا بيشارك اتصال حقيقي مع باقي الـ clients.
في وضع transaction pooling، الاتصال الحقيقي بيرجع للـ pool في لحظة COMMIT أو ROLLBACK. ده اللي بيخلّي 25 اتصال يخدم 4,000 client متزامن.
الحل في 12 سطر
تثبيت PgBouncer 1.22 على Ubuntu 22.04:
sudo apt install pgbouncerملف /etc/pgbouncer/pgbouncer.ini:
[databases]
production = host=127.0.0.1 port=5432 dbname=production
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 4000
default_pool_size = 25
reserve_pool_size = 5
reserve_pool_timeout = 3
server_idle_timeout = 600