بلاگ/خطای 502 Bad Gateway در Nginx: چرا رخ می‌دهد و چطور آن را رفع کنیم؟
به‌روز شده

خطای 502 Bad Gateway در Nginx: چرا رخ می‌دهد و چطور آن را رفع کنیم؟

1405/07/240 بازدید
خطای 502 Bad Gateway در Nginx: چرا رخ می‌دهد و چطور آن را رفع کنیم؟

خطای 502 Bad Gateway در Nginx: چرا رخ می‌دهد و چطور آن را رفع کنیم؟

کاور مقاله خطای 502 Bad Gateway در Nginx

وقتی سایتی که روی Nginx اجرا می‌شود ناگهان صفحه‌ی «502 Bad Gateway» را نشان می‌دهد، معمولاً خودِ Nginx مشکلی ندارد. این خطا یعنی Nginx به‌عنوان reverse proxy پاسخی از سرویس پشتی (بک‌اند) دریافت نکرده یا پاسخی نامعتبر گرفته است. رفع خطای 502 bad gateway nginx همیشه از بررسی همین رابطه بین Nginx و بک‌اند شروع می‌شود، نه از تغییر تصادفی تنظیمات.

در این مقاله چهار علت رایج این خطا را بررسی می‌کنیم، نشانه‌ی هرکدام در لاگ‌ها را نشان می‌دهیم و مراحل رفع هرکدام را روی سرور مجازی و سرور اختصاصی جدا توضیح می‌دهیم.

خطای 502 Bad Gateway دقیقاً چیست؟

در معماری رایج وب، Nginx جلوی سرویس اصلی (مثل PHP-FPM، Node.js، Gunicorn یا یک اپلیکیشن Go) قرار می‌گیرد و درخواست‌ها را به آن پاس می‌دهد. وقتی Nginx این درخواست را به بک‌اند می‌فرستد و:

  • بک‌اند اصلاً پاسخ نمی‌دهد،
  • اتصال قطع می‌شود،
  • یا پاسخ فرمت نادرستی دارد،

Nginx به جای نمایش محتوای واقعی، کد وضعیت 502 برمی‌گرداند. برخلاف خطای 500 که معمولاً از خود اپلیکیشن می‌آید، خطای 502 به مرز بین دو سرویس مربوط است؛ همین موضوع تشخیص آن را کمی متفاوت می‌کند.

نمودار ارتباط Nginx به‌عنوان reverse proxy با سرویس بک‌اند و محل بروز خطای 502 بین این دو

علت‌های رایج خطای 502 در Nginx

بک‌اند خاموش یا کرش‌کرده

شایع‌ترین دلیل، بالا نبودن سرویس پشتی است. PHP-FPM می‌تواند به‌خاطر مصرف بیش از حد حافظه کرش کند، یک پروسه‌ی Node.js ممکن است با یک exception مدیریت‌نشده متوقف شود، یا سرویس اصلاً هنوز استارت نخورده باشد.

تایم‌اوت بین Nginx و بک‌اند

اگر پردازش یک درخواست (مثلاً یک کوئری سنگین دیتابیس) بیشتر از مقدار proxy_read_timeout یا fastcgi_read_timeout طول بکشد، Nginx ارتباط را قطع می‌کند و 502 برمی‌گردد، حتی اگر بک‌اند درحال کار کردن باشد و در نهایت پاسخ می‌داد.

سایز بافر ناکافی برای هدرها

وقتی بک‌اند هدرهای HTTP بزرگ‌تر از proxy_buffer_size پیش‌فرض Nginx برمی‌گرداند (مثلاً به‌خاطر کوکی‌های زیاد یا هدرهای احراز هویت طولانی)، Nginx نمی‌تواند پاسخ را کامل بخواند و خطا می‌دهد.

مجوز سوکت یونیکس

اگر بک‌اند روی unix socket اجرا می‌شود (مثل /run/php/php8.2-fpm.sock)، و مالکیت یا پرمیشن سوکت با کاربری که Nginx تحت آن اجرا می‌شود (معمولاً www-data یا nginx) هم‌خوان نباشد، اتصال رد می‌شود.

اشتباه در تنظیمات upstream یا DNS

آدرس اشتباه در دستور proxy_pass، پورت بسته، یا نام‌دامنه‌ای در upstream که resolve نمی‌شود هم همین خطا را تولید می‌کند — این حالت معمولاً دائمی است، نه متناوب.

تشخیص علت با بررسی لاگ‌ها

قبل از تغییر هر تنظیمی، لاگ‌ها دقیقاً مشخص می‌کنند مشکل کجاست:

tail -f /var/log/nginx/error.log

چند پیام رایج و معنای آن‌ها:

  • connect() failed (111: Connection refused) → بک‌اند بالا نیست یا پورت/سوکت اشتباه است.
  • upstream timed out (110: Connection timed out) → مشکل تایم‌اوت، نه خاموشی سرویس.
  • upstream sent too big header while reading response header → مشکل سایز بافر.
  • Permission denied در کنار آدرس سوکت → مشکل مجوز.

در کنار این، وضعیت سرویس بک‌اند را هم چک کنید:

systemctl status php8.2-fpm
journalctl -u php8.2-fpm --since "10 min ago"

اگر سرویس اصلاً در حال ری‌استارت شدن پشت‌سرهم است (crash loop)، لاگ خودِ اپلیکیشن (نه لاگ Nginx) علت ریشه‌ای را نشان می‌دهد.

مراحل رفع خطای 502 بر اساس علت

جدول زیر پیام لاگ، علت احتمالی و اقدام مربوط به هرکدام را کنار هم می‌گذارد:

علتنشانه در لاگاقدام رفع
بک‌اند خاموش/کرش‌کردهConnection refusedری‌استارت سرویس، بررسی لاگ اپلیکیشن برای علت کرش
تایم‌اوتupstream timed outافزایش proxy_read_timeout و fastcgi_read_timeout، یا بهینه‌سازی کوئری سنگین
سایز بافر ناکافیtoo big headerافزایش proxy_buffer_size و proxy_buffers
مجوز سوکتPermission deniedتطبیق owner/group سوکت با کاربر Nginx، یا chmod مناسب
آدرس upstream اشتباهno resolver / 502 دائمی بدون پیام مشخصبررسی proxy_pass، تست با curl مستقیم به بک‌اند

برای تایم‌اوت و بافر، تغییر در فایل تنظیمات Nginx سایت (معمولاً داخل بلاک location یا server) به این شکل است:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_read_timeout 120s;
    proxy_buffer_size 16k;
    proxy_buffers 4 16k;
}

بعد از هر تغییر، تنظیمات را تست و Nginx را reload کنید:

nginx -t && systemctl reload nginx

روی سرور مجازی (VPS)

روی یک VPS معمولاً دسترسی کامل root دارید، پس مراحل بالا مستقیماً روی خود سرور اجرا می‌شود. نکته‌ی مهم: چون منابع VPS محدودتر از سرور اختصاصی است، یکی از علل غیرمستقیم خطای 502 می‌تواند تمام‌شدن RAM باشد — PHP-FPM یا هر بک‌اند دیگر وقتی حافظه کم می‌آورد توسط OOM killer کشته می‌شود و Nginx همان را به‌صورت 502 نشان می‌دهد. چک کردن free -h و لاگ dmesg | grep -i oom در این حالت لازم است.

روی سرور اختصاصی

روی سرور اختصاصی معمولاً منابع سخت‌افزاری محدودیت کمتری ایجاد می‌کنند، پس علت بیشتر به سمت تنظیمات (تایم‌اوت، بافر، سوکت) یا تعداد بالای پروسه‌های هم‌زمان بک‌اند متمایل است. اگر چند اپلیکیشن یا چند سایت روی یک سرور اختصاصی اجرا می‌شوند، PHP-FPM pool مربوط به همان سایت خاص را هم جدا بررسی کنید؛ گاهی فقط همان pool دچار مشکل است در حالی که سرویس اصلی سالم اجرا می‌شود.

چطور از بروز دوباره‌ی این خطا جلوگیری کنیم؟

چند اقدام ساده احتمال تکرار خطا را کم می‌کند:

  • مانیتورینگ وضعیت سرویس بک‌اند (مثل یک health-check ساده با curl در cron) تا قبل از این‌که کاربر خطا را ببیند متوجه قطعی شوید.
  • تعیین مقدار منطقی برای pm.max_children در PHP-FPM متناسب با RAM موجود، تا سرویس به‌جای کرش، درخواست‌ها را صف کند.
  • ثبت لاگ‌های Nginx و بک‌اند با timestamp یکسان تا بعداً بتوان دو لاگ را کنار هم مقایسه کرد.
  • تست تغییرات تنظیمات روی یک محیط staging قبل از اعمال روی سرور اصلی.

اگر منبع مشکل مکرراً کمبود RAM یا CPU در ساعات پربازدید است، این دیگر یک مشکل تنظیمات نیست — سروری با منابع متناسب با ترافیک واقعی لازم است.

برای چنین مواردی، سرویس سرور مجازی آریانت منابع قابل تنظیم و پایداری لازم برای اجرای پایدار بک‌اند را فراهم می‌کند، و در صورت نیاز به کنترل کامل منابع، سرور اختصاصی آریانت گزینه‌ی مناسب‌تری است.

جمع‌بندی

خطای 502 Bad Gateway در Nginx تقریباً همیشه از رابطه‌ی بین Nginx و بک‌اند می‌آید، نه از خودِ Nginx. چهار علت اصلی آن — خاموش بودن بک‌اند، تایم‌اوت، سایز بافر و مجوز سوکت — هرکدام پیام مشخصی در error.log دارند که مسیر رفع را مستقیم نشان می‌دهد. قبل از تغییر هر تنظیمی، همیشه از همان لاگ شروع کنید؛ این کار وقت زیادی صرفه‌جویی می‌کند.