مجله ایرانیکاسرورآموزش سرور، هاست، وردپرس و شبکه
آموزشی

رفع 504 Gateway Timeout در Nginx و Reverse Proxy

اگر سایت یا API شما پشت Nginx، HAProxy یا یک Reverse Proxy دیگر قرار دارد و با خطای 504 Gateway Timeout روبه‌رو شده‌اید، معنی آن معمولاً این است که Proxy توانسته Request را دریافت…

رفع 504 Gateway Timeout در Nginx و Reverse Proxy
خلاصه سریع این آموزش

اگر سایت یا API شما پشت Nginx، HAProxy یا یک Reverse Proxy دیگر قرار دارد و با خطای 504 Gateway Timeout روبه‌رو شده‌اید، معنی آن معمولاً این است که Proxy…

۱۲ دقیقه مطالعه ۰ دیدگاه ۱۳ مهر ۱۴۰۵ آخرین به‌روزرسانی

اگر سایت یا API شما پشت Nginx، HAProxy یا یک Reverse Proxy دیگر قرار دارد و با خطای 504 Gateway Timeout روبه‌رو شده‌اید، معنی آن معمولاً این است که Proxy توانسته Request را دریافت کند، اما Upstream یا Backend در زمان مورد انتظار پاسخ مناسب نداده است. در این وضعیت، افزایش Timeout ممکن است موقتاً خطا را پنهان کند؛ اما اگر علت اصلی Query کند، Worker قفل‌شده، CPU یا RAM اشباع، شبکه خراب یا Backend Down باشد، مشکل دوباره برمی‌گردد.

راه‌حل کوتاه: ابتدا Error Log و Access Log پروکسی را بررسی کنید و Upstream را مستقیم با curl تست کنید. سپس مشخص کنید مشکل در مرحله Connect، ارسال Request یا دریافت Response رخ می‌دهد. در Nginx سه Directive مهم proxy_connect_timeout، proxy_send_timeout و proxy_read_timeout هستند. فقط وقتی Backend سالم اما واقعاً کند است این Timeoutها را افزایش دهید؛ اگر Backend Crash، OOM یا کندی دیتابیس دارد، اول همان علت را برطرف کنید.

فهرست مطالب

خطای 504 Gateway Timeout چیست؟

در معماری Reverse Proxy معمولاً مسیر Request شبیه این است:

Client
  ↓
Reverse Proxy / Nginx
  ↓
Backend / Upstream
  ↓
Node.js / PHP-FPM / Python / Java / Docker / API

Nginx به‌عنوان Gateway یا Proxy درخواست کاربر را دریافت می‌کند و آن را برای Backend می‌فرستد. اگر Backend در محدوده زمانی مجاز پاسخ ندهد، Nginx ممکن است پاسخ 504 برای Client ارسال کند.

نمونه:

504 Gateway Time-out
nginx

تفاوت 504 با 502 Bad Gateway چیست؟

این دو خطا به هم نزدیک‌اند، اما یکسان نیستند.

  • 504 Gateway Timeout: Proxy منتظر پاسخ Upstream مانده و Timeout رخ داده است.
  • 502 Bad Gateway: Proxy نتوانسته پاسخ معتبر از Upstream بگیرد؛ مثلاً Connection refused، پاسخ خراب یا بسته‌شدن زودهنگام Connection.

مثلاً این پیام بیشتر به 504 مربوط است:

upstream timed out (110: Connection timed out) while reading response header from upstream

اما این مورد بیشتر به 502 یا خطای اتصال Upstream مربوط می‌شود:

connect() failed (111: Connection refused) while connecting to upstream

مرحله اول: Error Log Nginx را بررسی کنید

در Ubuntu و Debian معمولاً Error Log اصلی در این مسیر است:

/var/log/nginx/error.log

آخرین خطاها:

sudo tail -n 100 /var/log/nginx/error.log

مشاهده زنده هنگام بازتولید خطا:

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

نمونه خطای مهم:

upstream timed out (110: Connection timed out)
while reading response header from upstream,
client: 203.0.113.20,
server: example.com,
request: "GET /api/report HTTP/1.1",
upstream: "http://127.0.0.1:3000/api/report"

این خط نشان می‌دهد مشکل هنگام خواندن Header پاسخ از Backend روی Port 3000 رخ داده است.

سه Timeout مهم Nginx را بشناسید

proxy_connect_timeout

این مقدار مدت انتظار برای برقراری Connection با Upstream را کنترل می‌کند.

proxy_connect_timeout 10s;

اگر Backend Down، Port بسته یا شبکه مشکل داشته باشد، این مرحله اهمیت دارد.

proxy_send_timeout

این Directive فاصله زمانی بین عملیات ارسال Request از Nginx به Upstream را کنترل می‌کند:

proxy_send_timeout 60s;

proxy_read_timeout

این Directive فاصله زمانی بین دو عملیات خواندن متوالی از Upstream را کنترل می‌کند:

proxy_read_timeout 60s;

این عدد مدت کل Response نیست. اگر Backend در این مدت هیچ داده‌ای ارسال نکند، Connection بسته می‌شود.

مرحله دوم: Backend را بدون Reverse Proxy تست کنید

اگر Nginx درخواست را به این Upstream می‌فرستد:

proxy_pass http://127.0.0.1:3000;

همان Endpoint را مستقیم تست کنید:

curl -v http://127.0.0.1:3000/api/report

برای اندازه‌گیری زمان:

curl -s -o /dev/null \
  -w 'connect=%{time_connect} starttransfer=%{time_starttransfer} total=%{time_total}\n' \
  http://127.0.0.1:3000/api/report

اگر Direct Request نیز بسیار کند یا Fail است، مشکل اصلی Nginx نیست.

Backend واقعاً روی Port موردنظر Listen می‌کند؟

برای Port 3000:

sudo ss -ltnp 'sport = :3000'

اگر خروجی خالی است، Backend در حال Listen نیست.

با lsof:

sudo lsof -nP -iTCP:3000 -sTCP:LISTEN

مرحله سوم: لاگ Backend را هم‌زمان بخوانید

فقط نگاه کردن به Nginx کافی نیست. علت واقعی 504 اغلب در Backend دیده می‌شود.

اگر Backend با systemd اجرا شده است

sudo systemctl status myapp
sudo journalctl -u myapp -n 200 --no-pager

مشاهده زنده:

sudo journalctl -u myapp -f

اگر Backend داخل Docker است

docker ps
docker logs --tail=200 CONTAINER_NAME

برای Docker Compose:

docker compose ps
docker compose logs --tail=200 app

Timeout خود Backend را بررسی کنید

ممکن است Nginx دو دقیقه منتظر بماند اما Backend بعد از ۳۰ ثانیه Worker را Kill کند، یا برعکس.

برای رفع پایدار مشکل باید Timeoutهای لایه‌ها با هم هماهنگ باشند.

Gunicorn

اگر Python/Gunicorn دارید:

gunicorn app:app --workers 4 --timeout 120

در لاگ به پیام‌هایی مثل زیر دقت کنید:

WORKER TIMEOUT

PHP-FPM

در PHP-FPM ممکن است تنظیمی مثل زیر وجود داشته باشد:

request_terminate_timeout = 120s

برای PHP معمولاً در Nginx باید fastcgi_read_timeout را بررسی کنید، نه proxy_read_timeout.

رفع 504 در Nginx + PHP-FPM

اگر Nginx مستقیم به PHP-FPM وصل است:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;

    fastcgi_read_timeout 120s;
}

بعد:

sudo nginx -t
sudo systemctl reload nginx

اما اگر PHP Script واقعاً دو دقیقه درگیر Query یا Loop است، زیاد کردن Timeout راه‌حل اصلی نیست.

رفع 504 در Node.js

اگر Node.js پشت Nginx است، موارد زیر را بررسی کنید:

  • Queryهای کند دیتابیس
  • Requestهای طولانی Sync
  • CPU Block شدن Event Loop
  • Memory Leak
  • Promise یا API خارجی کند
  • Restart شدن Process توسط PM2 یا systemd

اگر با PM2 اجرا می‌شود:

pm2 list
pm2 logs APP_NAME --lines 200

Query کند دیتابیس؛ یکی از مهم‌ترین علت‌های 504

اگر فقط بعضی صفحات یا Endpointها Timeout می‌شوند، احتمال Query سنگین یا Lock دیتابیس وجود دارد.

برای مثال:

/api/report
/admin/export
/search
/orders?date=...

اگر Health Check سریع پاسخ می‌دهد اما یک Endpoint خاص بیشتر از ۶۰ ثانیه طول می‌کشد، مشکل معمولاً در همان Route یا وابستگی‌هایش است.

در چنین شرایطی باید Query Plan، Indexها، Lockها و زمان پاسخ دیتابیس بررسی شوند.

وابستگی به API خارجی

گاهی Backend شما خودش منتظر API دیگری است:

Client
 ↓
Nginx
 ↓
Your API
 ↓
External Payment / AI / SMS / Storage API

اگر API خارجی کند باشد، Request شما نیز معطل می‌ماند و در نهایت Nginx 504 می‌دهد.

در کد Backend برای APIهای خارجی Timeout مشخص تعریف کنید و اجازه ندهید Request بی‌نهایت منتظر بماند.

کمبود RAM و OOM Killer

اگر Backend به‌دلیل کمبود RAM Kill یا Restart شود، ممکن است درخواست‌ها با 502 یا 504 شکست بخورند.

بررسی:

free -h

لاگ OOM:

dmesg -T | grep -Ei 'oom|out of memory|killed process'

یا:

journalctl -k | grep -Ei 'oom|out of memory|killed process'

CPU و Load سرور را بررسی کنید

uptime
top

یا:

ps aux --sort=-%cpu | head

اگر Load Average شدیداً بالا است، Workerها ممکن است دیر CPU بگیرند و Response به‌موقع ارسال نشود.

I/O Wait بالا نیز می‌تواند 504 بسازد

Backend ممکن است CPU آزاد داشته باشد ولی منتظر Disk باشد.

اگر ابزار iostat نصب است:

iostat -xz 1

اگر await یا Utilization دیسک بالا باشد، Requestهایی که به Disk یا Database وابسته‌اند ممکن است کند شوند.

مقاله مرتبط

اگر سایت روی VPS گاهی باز نمی‌شود یا فقط بعضی Requestها از بیرون Fail می‌شوند، مقاله عیب‌یابی باز نشدن سایت روی VPS برای بررسی Firewall، Port، DNS، سرویس و شبکه می‌تواند مکمل این آموزش باشد.

رفع 504 در Docker Reverse Proxy

اگر Nginx و Backend هر دو داخل Docker هستند، بررسی کنید Backend Healthy و در شبکه درست باشد.

docker compose ps

Restart Count:

docker inspect -f '{{.RestartCount}}' CONTAINER_NAME

OOM:

docker inspect -f '{{.State.OOMKilled}}' CONTAINER_NAME

اگر Nginx داخل همان Compose است، بهتر است Upstream را با نام Service صدا بزند:

location / {
    proxy_pass http://app:3000;
}

از داخل Container Nginx نیز Backend را تست کنید:

docker compose exec nginx \
  curl -v http://app:3000/health

اگر Image Nginx ابزار curl ندارد، از Container دیباگ موقت در همان Network استفاده کنید.

اگر proxy_pass از Domain استفاده می‌کند

اگر Upstream با Hostname تعریف شده است، مشکل DNS داخلی نیز می‌تواند روی ارتباط اثر بگذارد.

مثال:

proxy_pass http://api.internal:3000;

از همان Host یا Container Nginx نام را Resolve کنید:

getent hosts api.internal

Latency و Packet Loss بین Proxy و Backend

اگر Nginx و Backend روی دو سرور جدا هستند، Network را هم بررسی کنید.

Latency:

ping -c 10 BACKEND_IP

Port:

nc -vz BACKEND_IP 3000

اگر Connection گاهی Timeout می‌شود، Route، Firewall، Packet Loss و Load شبکه باید بررسی شوند.

نمونه تنظیم معقول Reverse Proxy

برای Backendی که گاهی تا ۱۲۰ ثانیه برای پاسخ نیاز دارد:

location /api/ {
    proxy_pass http://127.0.0.1:3000;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_connect_timeout 10s;
    proxy_send_timeout 60s;
    proxy_read_timeout 120s;
}

این اعداد نمونه‌اند و باید متناسب با رفتار واقعی سرویس تنظیم شوند.

چرا Timeout خیلی بزرگ همیشه خوب نیست؟

اگر مقدار را مثلاً روی یک ساعت بگذارید، Requestهای گیرکرده می‌توانند Connectionها و Workerهای بیشتری را برای مدت طولانی درگیر نگه دارند.

برای عملیات‌های خیلی طولانی مثل:

  • تولید گزارش سنگین
  • Video Encoding
  • AI Inference طولانی
  • Backup
  • Import حجیم

اغلب معماری بهتر این است که Job وارد Queue شود و API سریع یک Job ID برگرداند؛ سپس Client وضعیت کار را جداگانه Poll یا Stream کند.

زمان پاسخ Upstream را داخل Access Log ثبت کنید

برای عیب‌یابی حرفه‌ای می‌توانید زمان‌های Upstream را داخل Log Format ثبت کنید.

نمونه در بخش http:

log_format upstream_timing '$remote_addr - $host '
    '"$request" $status '
    'rt=$request_time '
    'uct=$upstream_connect_time '
    'uht=$upstream_header_time '
    'urt=$upstream_response_time '
    'ua="$upstream_addr"';

سپس در Virtual Host:

access_log /var/log/nginx/upstream-timing.log upstream_timing;

بعد Configuration را تست کنید:

sudo nginx -t
sudo systemctl reload nginx

این Log کمک می‌کند بفهمید زمان در Connect، دریافت Header یا کل Response مصرف شده است.

اگر چند Backend دارید

ممکن است فقط یکی از Nodeها کند باشد:

upstream api_backend {
    server 10.0.0.11:3000;
    server 10.0.0.12:3000;
    server 10.0.0.13:3000;
}

هر Node را جداگانه تست کنید:

curl -s -o /dev/null -w '%{time_total}\n' http://10.0.0.11:3000/health
curl -s -o /dev/null -w '%{time_total}\n' http://10.0.0.12:3000/health
curl -s -o /dev/null -w '%{time_total}\n' http://10.0.0.13:3000/health

استفاده از proxy_next_upstream

Nginx می‌تواند در برخی خطاها یا Timeoutها درخواست را به Upstream دیگری ارسال کند:

proxy_next_upstream error timeout http_502 http_503 http_504;

اما باید در استفاده برای Requestهای غیر Idempotent مانند POST بسیار محتاط باشید؛ تکرار یک Request ممکن است عملیات را دوباره اجرا کند.

برای محدود کردن تعداد تلاش‌ها:

proxy_next_upstream_tries 2;

اگر جلوی Nginx یک Proxy دیگر قرار دارد

گاهی مسیر واقعی چنین است:

Client
 ↓
CDN / Cloud Proxy
 ↓
Load Balancer
 ↓
Nginx
 ↓
Backend

در این معماری هر لایه Timeout مخصوص خودش را دارد. اگر Nginx اجازه ۳۰۰ ثانیه بدهد اما Proxy بالادستی زودتر Connection را ببندد، کاربر همچنان Timeout می‌بیند.

بنابراین با مشاهده Response Header، Logهای هر لایه و تست مستقیم Origin مشخص کنید 504 از کجا صادر شده است.

Health Endpoint ایجاد کنید

برای Backend یک Endpoint بسیار سبک داشته باشید:

GET /health

و تست:

curl -i http://127.0.0.1:3000/health

اگر Health سریع است ولی Endpoint اصلی Timeout می‌شود، مشکل عمومی Network نیست و باید همان Route را بررسی کنید.

خطا را مرحله‌به‌مرحله بازتولید کنید

Terminal اول:

curl -vk https://example.com/api/report

Terminal دوم:

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

Terminal سوم:

sudo journalctl -u myapp -f

اگر خطا دقیقاً هم‌زمان با Exception یا Restart Backend رخ می‌دهد، دلیل واقعی را پیدا کرده‌اید.

ترتیب امن عیب‌یابی 504

  1. مشخص کنید کدام Proxy پاسخ 504 را تولید کرده است.
  2. Nginx Error Log را بررسی کنید.
  3. Upstream را مستقیم با curl تست کنید.
  4. Port و Process Backend را بررسی کنید.
  5. لاگ Backend را در همان زمان بخوانید.
  6. CPU، RAM، OOM و Disk I/O را بررسی کنید.
  7. Query دیتابیس و API خارجی را بررسی کنید.
  8. Timeout خود Backend را مشخص کنید.
  9. بعد از سالم بودن Backend، Timeoutهای Nginx را تنظیم کنید.
  10. نتیجه را با Log Timing و تست واقعی تأیید کنید.

اجرای Reverse Proxy و Backend روی VPS

اگر برای Nginx، Docker، Node.js، PHP-FPM، Python یا API به سرور لینوکسی نیاز دارید، می‌توانید پلن‌های خرید سرور مجازی ایران ایرانیکاسرور را بررسی کنید. برای سرویس‌های Production بهتر است منابع CPU و RAM، Monitoring، Backup و Timeoutهای هر لایه از ابتدا هماهنگ طراحی شوند.

تماس با پشتیبانی ایرانیکاسرور: 021-91302467

Rollback تنظیمات Nginx

قبل از تغییر فایل Virtual Host بکاپ بگیرید:

sudo cp /etc/nginx/sites-available/example.com \
  /etc/nginx/sites-available/example.com.backup

اگر تنظیم جدید نتیجه بدتری داشت:

sudo cp /etc/nginx/sites-available/example.com.backup \
  /etc/nginx/sites-available/example.com

sudo nginx -t
sudo systemctl reload nginx

اگر 504 فقط در ساعات پرترافیک رخ می‌دهد

این الگو معمولاً نیازمند بررسی هم‌زمان Resource، تعداد Workerها، Queue، دیتابیس و Upstream Latency است. اگر تشخیص لایه کند دشوار است، می‌توانید از خدمات کانفیگ و عیب‌یابی سرور ایرانیکاسرور استفاده کنید.

تماس با پشتیبانی ایرانیکاسرور: 021-91302467

اشتباه‌های رایج هنگام رفع 504

  • قرار دادن proxy_read_timeout 3600s بدون بررسی علت کندی؛
  • نادیده گرفتن Timeout خود Backend؛
  • یکی گرفتن 504 با Connection Refused؛
  • بررسی نکردن OOM Killer؛
  • نادیده گرفتن Query کند دیتابیس؛
  • Restart مکرر Nginx در حالی که Backend مشکل دارد؛
  • افزایش Workerها بدون محاسبه RAM؛
  • ندیدن Timeout CDN یا Load Balancer بالادستی؛
  • تست نکردن Backend بدون Reverse Proxy؛
  • انجام کار چنددقیقه‌ای در یک HTTP Request هم‌زمان به‌جای Queue.

سؤالات متداول

خطای 504 Gateway Timeout یعنی چه؟

یعنی یک Gateway یا Reverse Proxy برای دریافت پاسخ از Upstream بیش از زمان مجاز منتظر مانده است. علت می‌تواند Backend کند، Query دیتابیس، API خارجی، Resource کم یا Timeout نامناسب باشد.

برای رفع 504 فقط proxy_read_timeout را زیاد کنیم؟

خیر. ابتدا Backend را مستقیم تست کنید و لاگ آن را بررسی کنید. اگر Backend واقعاً سالم اما کند است، افزایش منطقی Timeout می‌تواند مناسب باشد؛ در غیر این صورت فقط مشکل اصلی پنهان می‌شود.

proxy_read_timeout چه چیزی را اندازه می‌گیرد؟

در Nginx این مقدار فاصله زمانی بین دو عملیات خواندن متوالی از Upstream را کنترل می‌کند، نه زمان کل انتقال Response.

proxy_connect_timeout چه تفاوتی دارد؟

proxy_connect_timeout مربوط به زمان برقراری Connection با Upstream است؛ در حالی که proxy_read_timeout بعد از اتصال، دریافت داده از Upstream را کنترل می‌کند.

چرا 504 فقط روی یک API خاص رخ می‌دهد؟

اگر سایر Endpointها سریع هستند، احتمال Query سنگین، Lock دیتابیس، API خارجی کند یا پردازش CPU-heavy در همان Route بالاست.

در PHP-FPM چه Timeoutی را بررسی کنیم؟

در Nginx برای FastCGI باید fastcgi_read_timeout بررسی شود. در PHP-FPM نیز تنظیماتی مثل request_terminate_timeout و زمان اجرای PHP اهمیت دارند.

چرا 504 فقط هنگام Load بالا دیده می‌شود؟

در Load بالا ممکن است Workerها، Connection Pool دیتابیس، CPU، RAM یا Disk I/O اشباع شوند و Response دیرتر از Timeout Proxy برسد.

آیا 504 می‌تواند از CDN باشد نه Nginx؟

بله. اگر چند Proxy یا Load Balancer جلوی Origin دارید، هر لایه می‌تواند Timeout خودش را داشته باشد. باید با Response Header و Logهای هر لایه منبع واقعی 504 را مشخص کنید.

جمع‌بندی: برای رفع 504 Gateway Timeout اول باید مشخص شود زمان در کجا تلف می‌شود. Error Log Nginx، تست مستقیم Upstream، لاگ Backend و بررسی Resource چهار نقطه شروع اصلی هستند. اگر Backend سالم است اما پاسخ طبیعی آن بیش از Timeout فعلی طول می‌کشد، proxy_read_timeout یا Timeout متناظر را افزایش دهید؛ اما اگر علت Query کند، OOM، Worker محدود یا API خارجی است، همان لایه باید اصلاح شود.

اشتراک‌گذاری مقاله
گفت‌وگو درباره آموزش

دیدگاه‌ها (۰)

هنوز دیدگاهی ثبت نشده است.

دیدگاه یا سؤال خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *