المدوّنة · الخوادم ولينكس

«504 Gateway Timeout»: لماذا يحدث وكيف تحلّه

· 7 دقائق قراءة

«504 Gateway Timeout»: لماذا يحدث وكيف تحلّه

تشير رسالة «504 Gateway Timeout» إلى أن خادم الويب الذي يستقبل طلبات الزوار (مثل Nginx أو وسيط Cloudflare) حاول الاتصال بالخادم الخلفي المسؤول عن معالجة البيانات (مثل معالج PHP-FPM أو خادم قاعدة البيانات)، لكن الأخير استغرق وقتاً أطول من الحد المسموح به للرد؛ فأغلق الوسيط الاتصال وأعلن انتهاء المهلة وفق معيار بروتوكول HTTP القياسي.

الفارق الجوهري بين خطأ 502 وخطأ 504 هو أن 502 يعني أن الخادم الخلفي أعاد رداً معطوباً أو منهاراً في التو واللحظة، بينما 504 يعني أن الخادم الخلفي يعمل بالفعل لكنه بطيء جداً وغارق في المعالجة حتى نفد صبر خادم الويب وتجاوز عداد الانتظار المسموح به. يستعرض هذا الدليل الأسباب الحقيقية لانتهاء المهلة وكيفية ضبط الحدود وتتبع العمليات العالقة لإعادة موقعك للعمل بأقصى سرعة واستقرار.

ماذا يحدث خلف الكواليس عند ظهور خطأ 504؟#

في معمارية استضافة المواقع الحديثة، يعمل Nginx كـ «وسيط عكسي» (Reverse Proxy)؛ فهو لا يعالج كود PHP بنفسه، بل يستقبل طلب صفحة الويب من المتصفح، ثم يمرره عبر مقبس محلي (UNIX Socket أو منفذ TCP الداخلي) لمعالج PHP-FPM ليتولى تنفيذ الأكواد وجلب البيانات من MySQL. يمتلك Nginx مؤقت عد تنازلي داخلي يبلغ افتراضياً ستين ثانية: إذا لم ينته PHP من معالجة الطلب وإرجاع الترويسات الأولى خلال هذه المهلة، يقطع Nginx الاتصال فوراً ويعيد للزائر كود HTTP 504 لحماية الخادم من تراكم آلاف الطلبات المعلقة التي قد تستهلك الذاكرة وتؤدي لإسقاط النظام بالكامل.

السبب الأول: انتهاء مهلة قراءة FastCGI في Nginx#

إذا كان موقعك ينفذ عمليات ثقيلة بطبيعتها تتطلب وقتاً أطول من ستين ثانية (مثل استيراد كتالوج منتجات ضخم في متجر ووكومرس، أو توليد فواتير PDF مجمعة، أو معالجة صور عالية الدقة)، فإن مهلة Nginx الافتراضية تكون غير كافية ويجب رفعها بتناسق:

  1. اتصل بالخادم عبر SSH بصلاحيات المدير.
  2. افتح ملف إعداد موقعك في Nginx (الموجود عادة في /etc/nginx/sites-available/):
    sudo nano /etc/nginx/sites-available/example.com
  3. ابحث عن كتلة معالجة PHP التي تبدأ بـ location ~ \.php$، وأضف التوجيهات التالية بمهلة ثلاثمائة ثانية (خمس دقائق):
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    
        # رفع مهلة انتظار الاستجابة لمعالج PHP
        fastcgi_read_timeout 300;
        fastcgi_send_timeout 300;
    }
    لا ترفع fastcgi_connect_timeout هنا؛ فهي مهلة إنشاء الاتصال بمعالج PHP لا مهلة معالجة الطلب، وتوثيق Nginx ينص على أنها لا تتجاوز عادةً 75 ثانية. أما fastcgi_read_timeout فتُحسب بين عمليتي قراءة متتاليتين لا لكامل الرد.
  4. إذا كان خادمك يستخدم Nginx كوسيط أمام خادم Apache (Proxy Pass)، أضف هذه التوجيهات داخل كتلة location /:
    proxy_send_timeout 300;
    proxy_read_timeout 300;
    والأمر نفسه ينطبق على proxy_connect_timeout: لا تتجاوز عادةً 75 ثانية، والمهلة التي تحكم الردود البطيئة هي proxy_read_timeout.
  5. اختبر صحة إعدادات Nginx ثم أعد تحميل الخدمة بأمان:
    sudo nginx -t
    sudo systemctl reload nginx

السبب الثاني: مهلة تنفيذ سكربتات PHP ومجمع العمليات (PHP-FPM)#

رفع وقت Nginx وحده لا يحل المشكلة إذا كان محرك PHP نفسه يقطع السكربت عند ثلاثين ثانية؛ فالسكربت سيتوقف بينما Nginx لا يزال ينتظر رداً لن يصل أبداً. يجب مزامنة مهلة PHP مع مهلة خادم الويب على مستويين:

1. ضبط ملف php.ini الأساسي#

افتح ملف إعدادات PHP لمعالج FPM:

sudo nano /etc/php/8.2/fpm/php.ini

عدل القيم التالية لتسمح بمعالجة أطول وذاكرة كافية:

max_execution_time = 300
max_input_time = 300
memory_limit = 256M

2. ضبط مجمع العمليات (Pool Configuration)#

هناك متغير خفي في PHP-FPM يغفل عنه معظم مديري الخوادم اسمه request_terminate_timeout؛ فإذا وصل السكربت لهذا الحد يقتله المعالج فوراً بغض النظر عما كُتب في php.ini:

sudo nano /etc/php/8.2/fpm/pool.d/www.conf

ابحث عن السطر التالي وأزل الفاصلة المنقوطة من بدايته وعيّن القيمة إلى ثلاثمائة ثانية:

request_terminate_timeout = 300

ثم أعد تشغيل خدمة PHP-FPM لتطبيق الإعدادات الجديدة:

sudo systemctl restart php8.2-fpm

السبب الثالث: استعلامات قاعدة بيانات بطيئة أو جداول مقفلة#

المسبب الأكثر خطورة لخطأ 504 في المواقع الكبيرة ليس بطء كود PHP، بل استعلامات SQL المعقدة التي تفحص مئات الآلاف من السجلات دون فهارس سليمة، أو وجود جداول مقفلة تنتظر انتهاء عملية كتابة أخرى:

  • افحص الاستعلامات الحية الجارية في قاعدة البيانات عبر سطر أوامر MySQL:
    SHOW FULL PROCESSLIST;
  • ابحث عن أي سطر تتجاوز فيه قيمة حقل الوقت ستين أو مائة ثانية وحالته Locked أو Sending data أو Copying to tmp table.
  • إذا وجدت استعلاماً معلقاً يمنع باقي العمليات، يمكنك إنهاؤه فوراً باستخدام معرفه الرقمي:
    KILL 1234;
    (استبدل 1234 برقم المعرف الظاهر في عمود Id).
  • فعّل سجل الاستعلامات البطيئة (Slow Query Log) في ملف /etc/mysql/my.cnf لمعرفة الاستعلامات التي تتجاوز ثانيتين وإعادة فهرستها بمساعدة المطور:
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/mysql-slow.log
    long_query_time = 2
  • تأكد من تحويل كافة جداول الموقع إلى محرك InnoDB الحديث، وتجنب محرك MyISAM القديم الذي يقفل الجدول بأكمله عند تعديل أي صف واحد.

السبب الرابع: طلبات HTTP الخارجية المعلقة (External APIs & Webhooks)#

في مواقع ووردبريس، تستخدم العديد من الإضافات دالة wp_remote_get أو مكتبات cURL للاتصال بخدمات خارجية؛ مثل بوابات الدفع، أو مزامنة النشرات البريدية، أو خدمات التحقق من التراخيص. إذا توقف خادم تلك الخدمة الخارجية أو تأخر في الرد، وظل كود الإضافة ينتظر دون وضع مهلة زمنية صارمة، سيتجمد معالج PHP الخاص بموقعك بالكامل حتى يبلغ حد مهلة Nginx ويطلق خطأ 504 أمام الزائر. يمكنك اكتشاف ذلك بمراقبة الاتصالات الشبكية الخارجة من السيرفر عبر أمر netstat -ntp أو تفقد سجل أخطاء ووردبريس.

السبب الخامس: انتهاء مهلة وسيط Cloudflare#

إذا كان موقعك يستخدم شبكة Cloudflare، فهناك فارق بصري مهم يجب الانتباه له لتحديد مكان العطل بدقة:

  • شاشة خطأ تحمل شعار وتصميم Cloudflare الصريح برقم 524: تعني أن شبكة كلاود فلير اتصلت بسيرفر استضافتك الأصلي لكنه لم يُرسل استجابة HTTP خلال المهلة الافتراضية البالغة 125 ثانية. هذا يؤكد أن المشكلة تقع داخل خادم استضافتك، ويجب تحسين سرعة معالجة السيرفر لأن رفع هذه المهلة متاح لعملاء خطة Enterprise فقط.
  • شاشة 504 نصية عادية من Nginx: تعني أن المشكلة حدثت محلياً داخل السيرفر قبل وصول الرد للوسيط الخارجي.

مقارنة معمارية: خطأ 502 مقابل خطأ 504#

وجه المقارنة خطأ 502 Bad Gateway خطأ 504 Gateway Timeout
حالة الخادم الخلفي (PHP/DB) منهار تماماً، متوقف، أو أعاد ترويسات تالفة وفارغة يعمل بنشاط لكنه غارق في مهمة طويلة تجاوزت الوقت
سرعة ظهور الخطأ فوري ولحظي بمجرد طلب الصفحة يظهر بعد انتظار طويل (عادة بعد ستين ثانية كاملة)
المتغير الأساسي في Nginx فشل fastcgi_pass في المصافحة أو عودة كود معطوب تجاوز حد fastcgi_read_timeout المحدد
العلاج الأساسي إعادة تشغيل خدمة PHP-FPM والتأكد من المقبس رفع مهلات الانتظار وتحسين الاستعلامات والمهام الثقيلة

كيف تتأكد أن المشكلة حُلت تماماً؟#

  1. أعد تنفيذ العملية التي كانت تتسبب في تعليق المتصفح (مثل تصدير تقرير أو استيراد ملف بيانات).
  2. راقب سجل أخطاء Nginx لحظياً أثناء المعالجة عبر الطرفية:
    sudo tail -f /var/log/nginx/error.log
    إذا اكتملت العملية بنجاح دون ظهور سطر upstream timed out (110: Connection timed out) while reading response header from upstream، فهذا برهان قاطع على نجاح الإعداد.
  3. قس وقت استجابة الخادم الإجمالي باستخدام أمر curl لفحص سرعة المصافحة:
    curl -s -w "Total Time: %{time_total}s\n" -o /dev/null https://example.com/slow-endpoint
    يجب أن تكتمل الاستجابة بسلاسة دون انقطاع الاتصال.

المشاكل الشائعة وحلولها#

رفع المهلة إلى ثلاثمائة ثانية ولم يتغير شيء وظل الخطأ يظهر عند ستين ثانية
تحقق مما إذا كان هناك وسيط أو جدار حماية عكسي أمام السيرفر (مثل Apache يعمل خلف Nginx، أو خادم توازن أحمال Load Balancer). يجب رفع المهلة في جميع الطبقات الوسيطة تباعاً.
اختفاء الخطأ ولكن خادم السيرفر أصبح بطيئاً جداً لجميع الزوار
رفع مهلة التنفيذ لفترات طويلة مع كثرة الطلبات المتزامنة يجعل معالجات PHP محجوزة لفترات طويلة، مما يستنفد عدد العمال (pm.max_children). الحل الحقيقي هنا هو نقل العمليات الثقيلة لتعمل في الخلفية بنظام الطوابير والكرون جوب (Cron Jobs) بدلاً من تنفيذها مباشرة داخل طلب صفحة الويب.

المصادر#

التعليقات

كن أول من يشارك رأيه أو تجربته.

أضف تعليقاً أو سؤالاً

سجّل الدخول لتعجب بالتعليقات المفيدة وترفعها لأعلى النقاش. سجّل الدخول

لا يُنشر، ولا نرسل إليه شيئاً.

يظهر التعليق بعد مراجعته. الروابط لا تُفعَّل.

تبني موقعاً عربياً؟

سكربتات وقوالب وإضافات وخوادم — مصمّمة للمواقع العربية.

تصفّح المنتجات