الخطأ 504 يعني أن الصفحة كانت ما تزال تُبنى حين توقّف Nginx عن الانتظار. لم ينهر شيء. بل استغرق شيءٌ ما وقتًا أطول ممّا يُسمح له، والسؤال الصادق هو: ما هو.
جِد الطلب البطيء
يكتب PHP-FPM سجلًّا للبطء إن طلبت منه ذلك، ويطبع الدالة التي كانت تعمل بالضبط حين نفدت الساعة. وهذا هو الجواب كلّه، فشغّله قبل أن تغيّر أي شيء آخر.
; in the pool config
request_slowlog_timeout = 5s
slowlog = /var/log/php8.3-fpm-slow.log
- أعِد تحميل PHP-FPM — systemctl reload php8.3-fpm
- أعِد إنتاج الصفحة البطيئة — طلبٌ واحد يكفي.
- اقرأ الأثر — tail -60 /var/log/php8.3-fpm-slow.log — والإطار الأعلى هو ما كان يعمل.
الأشياء الثلاثة التي يكون هو غالبًا
- نداءٌ خارجيّ بلا مهلة. بوّابةُ دفعٍ أو واجهةٌ برمجية كفّت عن الإجابة ستُمسك صفحتك ما دام المقبس مفتوحًا. كل طلب صادر يحتاج مهلته الخاصّة، وخمس ثوانٍ كرمٌ.
- واستعلامٌ بلا فهرس. فجدولٌ كان صغيرًا العام الماضي ليس صغيرًا الآن. وسجلّ الاستعلامات البطيئة يسمّيه.
- ودورةٌ على مجلّد. فمجلّدٌ نما إلى مئة ألف ملفّ يستغرق سرده دقائق.
ورفعُ fastcgi_read_timeout يُذهب الخطأ ويترك الزائر يحدّق في تبويب فارغ خمس دقائق بدل دقيقة. أصلح الانتظار لا الحدّ.
ومتى يكون رفعه صوابًا
حالةٌ واحدة: مهمّةٌ طويلة مقصودة أطلقتها أنت — ترحيلٌ أو استيرادٌ كبير — على صفحة لا يستعملها غيرك. ارفعه لذلك الموضع وحده، لا عالميًّا أبدًا.
location = /admin/import.php {
fastcgi_read_timeout 600;
}
وكل ما يستطيع زائرٌ إطلاقه مكانه طابور. تبدأ الصفحة المهمّة وتعود فورًا؛ والمهمّة تبلّغ حين تنتهي.