خطأ "connection refused" في PostgreSQL: ماذا يعني وكيف تصلحه
«Connection refused» رفضٌ على مستوى TCP: لا شيء قَبِل الاتصال على ذلك العنوان والمنفذ. وهذه الحقيقة وحدها تستبعد نصف المشتبهين المعتادين.
ماذا يعني "connection refused" فعليًا
يحدث «connection refused» تحت طبقات المصادقة والصلاحيات في PostgreSQL: أرسل عميلك محاولة اتصال TCP فتلقى رفضًا فعّالًا — إما لا توجد عملية تستمع على ذلك العنوان والمنفذ، أو جدار ناري رفض الحزمة. لم يرَ PostgreSQL الاتصال أصلًا. وهذه الدقة مهمة، لأنها تستبعد فورًا كلمات المرور وقواعد pg_hba.conf وصلاحيات قاعدة البيانات كأسباب: فكلها تنتج أخطاء مختلفة بعد قيام الاتصال.
قارن الأخطاء المجاورة: "no pg_hba.conf entry for host …" تعني أن الخادم قابل للوصول لكنه رفض عنوان عميلك أو أسلوب مصادقته؛ و"password authentication failed" تعني بيانات الاعتماد؛ و"FATAL: sorry, too many clients already" تعني استنفاد max_connections. أما الاتصال الذي يعلّق ثم تنقضي مهلته (بدل أن يُرفض) فيشير إلى جدار ناري يُسقط الحزم بصمت أو مشكلة توجيه. كل رسالة ترسلك إلى مكان مختلف — فاقرأها بدقة.
الأسباب الجذرية الشائعة لرفض الاتصال
PostgreSQL لا يعمل
الخادم انهار، أو فشل في الإقلاع بعد تغيير إعدادات، أو قُتل بنفاد الذاكرة، أو ببساطة لم تُفعَّل الخدمة بعد إعادة تشغيل الجهاز. والإقلاع الفاشل بسبب خطأ مطبعي في postgresql.conf أو قرص ممتلئ هو الحالة الكلاسيكية — والسجلات تسمّي السطر المكسور بالضبط.
عدم تطابق listen_addresses أو المنفذ
افتراضيًا يستمع PostgreSQL على localhost فقط. فالعميل المتصل من جهاز آخر يُرفض لأن الخادم لم يرتبط بتلك الواجهة أصلًا — والعلاج بـ listen_addresses = '*' (أو عناوين محدّدة) مع سطر مطابق في pg_hba.conf. والمنفذ غير الافتراضي أو وجود عنقودين على جهاز واحد يسبّبان العرَض نفسه.
جدار ناري أو مجموعة أمان ترفض المنفذ 5432
قواعد REJECT في iptables/nftables، أو مجموعات أمان سحابية، أو قائمة سماح في قاعدة بيانات مُدارة لا تشمل عنوان عميلك. قاعدة REJECT تنتج «connection refused»؛ وقاعدة DROP تنتج تعليقًا ثم مهلة — والفرق يخبرك أي نوع من القواعد تواجه.
مضيف خاطئ: ارتباك DNS والحاويات وlocalhost
العميل يشير إلى اسم DNS قديم، أو عنوان IP سابق بعد ترحيل — أو، داخل حاوية، إلى localhost الذي يعني الحاوية نفسها لا مضيف قاعدة البيانات. في Docker Compose اسم المضيف هو اسم الخدمة؛ ومن الحاوية إلى الجهاز المضيف يكون host.docker.internal أو عنوان المضيف.
كيف تحقّق فيه وتصلحه
تأكد من نص الخطأ الحرفي، ثم سِر في المسار من عملية الخادم إلى مقبس الاستماع إلى قابلية الوصول الشبكي — بهذا الترتيب، لأن نتيجة كل خطوة تحدّد التالية.
- 1
اقرأ رسالة الخطأ الحرفية
«connection refused» ← لا شيء يستمع أو جدار ناري بقاعدة REJECT. «timed out» ← قاعدة DROP أو توجيه. «no pg_hba.conf entry» ← الخادم قابل للوصول والمشكلة في إعدادات المصادقة. «too many clients» ← قابل للوصول والاتصالات مستنفدة. وتجاوز هذه الخطوة هو ما يجعل مهندسًا يقضي ساعة في pg_hba.conf لخادم لا يعمل أصلًا.
- 2
تحقّق أن الخادم يعمل
على مضيف قاعدة البيانات: systemctl status postgresql (أو docker ps أو kubectl get pods للإعدادات المحوّاة)، ثم اقرأ سجل PostgreSQL بحثًا عن أخطاء إقلاع — سطر إعداد خاطئ، قرص ممتلئ، تعافٍ فاشل. إن لم يكن يعمل فالأسطر الأخيرة في السجل تشرح السبب؛ أصلحه ويختفي الرفض.
- 3
افحص ما يستمع عليه
نفّذ ss -lntp | grep 5432 (أو netstat). يستمع على 127.0.0.1:5432 فقط؟ سيُرفض العملاء البعيدون — اضبط listen_addresses في postgresql.conf وأعد التشغيل (لا يكفي إعادة التحميل). يستمع على منفذ مختلف؟ وائم العميل. لا شيء في القائمة؟ العملية ليست قائمة فعلًا.
- 4
اختبر الوصول من جهاز العميل
من الجهاز الذي يتلقى الخطأ: psql -h <host> -p 5432 أو nc -zv <host> 5432. الرفض من العميل مع نجاح الاتصال محليًا على الخادم يحصر المشكلة في المسار الشبكي أو عنوان الارتباط. وتأكد أيضًا أن اسم المضيف يُحلّ إلى عنوان IP الذي تتوقعه.
- 5
افحص الجدران النارية ومجموعات الأمان
راجع قواعد iptables/nftables على الخادم، ومجموعات الأمان السحابية، وأي قائمة سماح عناوين في قاعدة بيانات مُدارة. أضف عنوان العميل (أو شبكته) إلى قواعد السماح للمنفذ 5432. ومع الخدمات المُدارة تذكّر NAT الصادر — فقاعدة البيانات ترى عنوان خروجك لا عنوان جهازك الخاص.
- 6
في الحاويات، تحقّق من المسار الشبكي
تأكد من اسم المضيف الصحيح للبنية (اسم الخدمة في Compose، وDNS الخدمة في Kubernetes، وhost.docker.internal من الحاوية إلى المضيف)، وأن تخطيط المنافذ ينشر 5432 فعلًا، وأن الحاويتين تتشاركان شبكة. ادخل حاوية العميل بـ docker exec واختبر بـ nc لترى ما تراه هي.
كيف تمنع حوادث رفض الاتصال
- فعّل خدمة PostgreSQL وراقبها على مستوى النظام حتى لا تتركها إعادة تشغيل أو انهيار متوقفةً بصمت.
- تحقّق من تغييرات الإعدادات بإعادة تحميل أو تشغيل في بيئة staging أولًا — فسطر خاطئ واحد في postgresql.conf قد يمنع الخادم من الإقلاع.
- راقب قرص مضيف قاعدة البيانات وذاكرته والمنفذ نفسه — فالقرص الممتلئ سبب رئيسي لتوقف PostgreSQL المفاجئ.
- أدر قواعد الجدار الناري وقوائم السماح كشيفرة بحيث يكون تغيير عنوان عميل فرقًا مُراجَعًا لا مفاجأة في الثانية فجرًا.
- استخدم تجميع الاتصالات وإعادة المحاولة بتراجع تدريجي في التطبيقات حتى لا تتحوّل إعادة تشغيل قصيرة إلى فشل يعمّ التطبيق.
كيف يساعدك AllStak مع اتصال قاعدة البيانات
تراقب مراقبة البنية التحتية في AllStak مضيف قاعدة البيانات نفسه — المعالج والذاكرة والقرص والخدمات العاملة — فيظهر القرص الممتلئ أو قتل نفاد الذاكرة الذي أسقط PostgreSQL على رسم بياني بوقت محدّد. وتصل أخطاء اتصال تطبيقك إلى تتبّع الأخطاء في اللحظة نفسها، مجمَّعة في مشكلة واحدة بدل سيل من التكرارات.
ومع وجود سجلات PostgreSQL وسجلات تطبيقك في المنصّة نفسها، يجلس سطر «could not connect» من التطبيق بجانب آخر خطأ إقلاع لقاعدة البيانات على خط زمني واحد — وهذا غالبًا كل الربط الذي يحتاجه اتصال مرفوض. كما تستطيع فحوصات التشغيل مراقبة منفذ TCP من الخارج، فتؤكد التعافي بمعزل عن التطبيق.
أسئلة شائعة عن رفض اتصال PostgreSQL
ما الفرق بين "connection refused" و"connection timed out"؟
الرفض ردٌّ فعّال — وصلت حزمتك إلى جهاز أجاب «لا شيء هنا»: لا مستمع على المنفذ، أو قاعدة REJECT في جدار ناري. أما انقضاء المهلة فيعني أن الحزم اختفت في صمت: قاعدة DROP، أو مشكلة توجيه، أو مضيف متعذّر الوصول. الرفض ← افحص الخادم وعنوان الارتباط؛ والمهلة ← افحص المسار الشبكي.
هل هذه مشكلة pg_hba.conf؟
لا. يُقيَّم pg_hba.conf بعد قيام اتصال TCP؛ ورفضه ينتج الخطأ الصريح "no pg_hba.conf entry for host …". إذا كنت ترى «connection refused» فإن PostgreSQL لم يستلم الاتصال أصلًا — انظر إلى العملية وlisten_addresses والمنفذ والجدران النارية بدلًا منه.
هل يمكن أن يكون السبب استنفاد max_connections؟
لا — فذلك ينتج خطأ مختلفًا وصريحًا: "FATAL: sorry, too many clients already"، ويصل عبر اتصال قائم بنجاح. إن رأيت ذلك الخطأ فالعلاج تجميع الاتصالات (pgbouncer أو مجمّع إطارك)، أو تعقّب تسريبات الاتصالات، أو رفع max_connections عن قصد. أما «refused» فيعني أن المحادثة لم تبدأ قط.
لماذا يعمل محليًا على الخادم ولا يعمل من جهازي؟
السبب شبه المؤكد هو listen_addresses. الافتراضي localhost، فتنجح الاتصالات عبر مقبس Unix أو 127.0.0.1 بينما يُرفض كل ما يصل على واجهة الشبكة. اضبط listen_addresses كما يلزم، وأعد تشغيل PostgreSQL، وأضف سطرًا في pg_hba.conf لشبكة عميلك — ثم افحص الجدار الناري، فهو العرَض نفسه على بُعد طبقة.
اعرف متى يقع مضيف قاعدة بياناتك في مشكلة
يراقب AllStak قرص المضيف وذاكرته وخدماته، ويضع أخطاء اتصال تطبيقك وسجلات قاعدة البيانات على خط زمني واحد.