Blog Article

حل خطاهای متداول استقرار جنگو با Nginx و Gunicorn روی لینوکس سرور

راهنمای جامع عیب‌یابی و حل خطاهای استقرار جنگو با Nginx و Gunicorn روی لینوکس سرور، رفع ارور 502، مدیریت Static Files و بهینه‌سازی مصرف RAM.

حل خطاهای متداول استقرار جنگو با Nginx و Gunicorn روی لینوکس سرور

رفع خطای 502 در استقرار جنگو با Nginx و Gunicorn

استقرار پروژه‌های پایتون در محیط پروداکشن معمولاً با ترکیب محبوب Nginx و Gunicorn انجام می‌شود، اما انتقال برنامه از سیستم لوکال به یک لینوکس سرور واقعی اغلب چالش‌ها و خطاهای پیش‌بینی‌نشده‌ای به همراه دارد. مواجهه با خطای ۵۰۲ Bad Gateway، لود نشدن استایل‌ها و تصاویر، یا قفل شدن سرور به دلیل اتمام حافظه RAM از جمله مواردی هستند که هر توسعه‌دهنده بک‌اند و متخصص دواپس حداقل یک بار با آن‌ها روبه‌رو شده است.

در فرآیند توسعه و آموزش جنگو، تمرکز اصلی معمولاً بر روی منطق کدنویسی و پایگاه داده است؛ در نتیجه هنگام ورود به مباحث استقرار (Deployment) و ارتباط لایه‌های وب‌سرور، اپلیکیشن سرور و سیستم‌عامل، خطاهای پیکربندی رخ می‌دهند. داشتن یک رویکرد سیستماتیک برای اشکال‌زدایی (Debugging) باعث می‌شود که در سریع‌ترین زمان ممکن ریشه خطا را شناسایی و سرویس را بدون اختلال فعال نگه دارید.

در این مقاله تخصصی، به بررسی مرحله‌به‌مرحله و ریشه‌ای خطاهای متداول استقرار جنگو با Nginx و Gunicorn می‌پردازیم؛ از تنظیمات سوکت‌های یونیکس و رفع مجوزهای فایل‌های استاتیک گرفته تا فرمول‌های طلایی مدیریت Workerها و بهینه‌سازی منابع سرور برای هندل کردن درخواست‌های هم‌زمان بالا.


۱. عیب‌یابی خطای 502 Bad Gateway و تنظیم سوکت‌های Gunicorn

خطای 502 Bad Gateway یکی از پرتکرارترین خطاها در محیط‌های عملیاتی است. این خطا به این معناست که وب‌سرور Nginx نتوانسته با موفقیت به اپلیکیشن‌سرور Gunicorn متصل شود یا پاسخی از آن دریافت کند.

+-----------+       HTTP Request       +-----------+       Unix Socket / TCP       +------------+
|  Client   | -----------------------> |   Nginx   | ----------------------------> |  Gunicorn  |
| (Browser) | <----------------------- | (Reverse  | <---------------------------- |  (WSGI App |
|           |   502 Bad Gateway (X)    |  Proxy)   |    Connection Refused / Fail  |  - Django) |
+-----------+                          +-----------+                               +------------+

بررسی وضعیت سرویس Systemd و لاگ‌های سیستمی

قبل از هر کاری، باید وضعیت زنده بودن پروسه Gunicorn را بررسی کنید. در صورتی که Gunicorn متوقف شده باشد، Nginx مقصدی برای هدایت ترافیک نخواهد داشت.

برای بررسی وضعیت، دستور زیر را اجرا کنید:

sudo systemctl status gunicorn.service

اگر سرویس غیرفعال یا در وضعیت failed قرار دارد، با دستور زیر آخرین لاگ‌های خطا را تحلیل کنید:

sudo journalctl -u gunicorn.service -e --no-pager

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

حل مشکل مجوزها و فایل سوکت (Unix Sockets vs TCP Port)

ارتباط میان Nginx و Gunicorn معمولاً به دو روش برقرار می‌شود:

  1. پورت شبکه محلی (TCP): مثلاً 127.0.0.1:8000
  2. سوکت سیستم‌عامل (Unix Domain Socket): مثلاً unix:/run/gunicorn.sock

استفاده از Unix Socket کارایی و سرعت بالاتری دارد اما رایج‌ترین دلیل خطای ۵۰۲، مجوزهای دسترسی ناصحیح به این فایل است. کاربر www-data (که وب‌سرور Nginx با آن اجرا می‌شود) باید اجازه خواندن و نوشتن روی فایل سوکت را داشته باشد.

نمونه تنظیمات صحیح سوکت در فایل /etc/systemd/system/gunicorn.socket:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock
SocketUser=www-data
SocketGroup=www-data
SocketMode=0660

[Install]
WantedBy=sockets.target

اگر از پورت TCP استفاده می‌کنید، مطمئن شوید پارامتر proxy_pass در تنظیمات Nginx با آدرس بایند شده در Gunicorn یکسان باشد:

# /etc/nginx/sites-available/myproject
location / {
    include proxy_params;
    proxy_pass http://unix:/run/gunicorn.sock;
    # یا در حالت شبکه: proxy_pass http://127.0.0.1:8000;
}

پس از اصلاح، سرویس‌ها را مجدداً بارگذاری کنید:

sudo systemctl daemon-reload
sudo systemctl restart gunicorn.socket gunicorn.service
sudo systemctl restart nginx

۲. رفع مشکلات دسترسی و بارگذاری فایل‌های استاتیک و رسانه‌ای (Static & Media Files)

یکی دیگر از چالش‌های رایج پس از غیرفعال کردن DEBUG = False در جنگو، لود نشدن استایل‌های CSS، جاوااسکریپت و تصاویر در پنل ادمین یا بخش کاربری سایت است. در محیط پروداکشن، وظیفه تحویل فایل‌های ایستا نباید بر عهده جنگو یا Gunicorn باشد، بلکه Nginx باید مستقیماً آن‌ها را تحویل دهد.

                              +--------------------+
                              | Nginx Entry Point  |
                              +---------+----------+
                                        |
                   +--------------------+--------------------+
                   |                                         |
     Request for /static/ or /media/            Request for /api/ or Dynamic Views
                   |                                         |
     +-------------v-------------+              +------------v------------+
     | Static Storage Directory  |              | Gunicorn WSGI Worker    |
     | (/var/www/myproject/...)  |              | (Django Backend Logic)  |
     +---------------------------+              +-------------------------+

تنظیمات صحیح settings.py و اجرای Collectstatic

برای انتقال تمام فایل‌های استاتیک اپلیکیشن‌ها به یک مسیر واحد، پارامترهای زیر را در فایل settings.py بازبینی کنید:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

سپس دستور تجمیع فایل‌ها را داخل محیط مجازی (Virtualenv) اجرا کنید:

python manage.py collectstatic --noinput

اگر فرآیند استقرار خود را در کانتینرها اجرا می‌کنید، راهنمای آموزش گام به گام داکرایز کردن پروژه جنگو به همراه PostgreSQL و Redis نحوه هندل کردن این دستورات را در زمان بیلد داکر به شکل کامل توضیح داده است.

پیکربندی بلوک‌های Nginx برای Static و Media

در فایل کانفیگ سایت در Nginx، باید بلوک‌های location مجزا برای مسیرهای استاتیک و مدیا تعریف کنید تا Nginx بدون درگیر کردن پایتون فایل‌ها را سرو کند:

server {
    listen 80;
    server_name example.com www.example.com;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {
        alias /home/ubuntu/myproject/staticfiles/;
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }

    location /media/ {
        alias /home/ubuntu/myproject/media/;
        expires 7d;
        add_header Cache-Control "public, no-transform";
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

نکته کلیدی: به اسلش (/) انتهایی در مقادیر location و alias دقت کنید. ناهماهنگی در اسلش‌های پایانی منجر به خطای ۴۰۴ در پیدا کردن مسیر فایل‌ها می‌شود.

رفع خطای ۴۰۳ Forbidden با تنظیم مالکیت و مجوزها

اگر مسیرها درست باشند اما باز هم خطای ۴۰۳ دریافت کنید، دسترسی لینوکسی Nginx به پوشه پروژه محدود است. برای حل این مشکل، مجوزهای استاندارد را اعمال کنید:

sudo chown -R ubuntu:www-data /home/ubuntu/myproject/staticfiles
sudo chown -R ubuntu:www-data /home/ubuntu/myproject/media
sudo chmod -R 755 /home/ubuntu/myproject/staticfiles
sudo chmod -R 775 /home/ubuntu/myproject/media

۳. بهینه‌سازی مصرف RAM و مدیریت نشست‌های هم‌زمان روی لینوکس سرور

استقرار یک وب‌سایت جنگو بدون کانفیگ منابع می‌تواند به سرعت منجر به خطای Out of Memory (OOM) و از کار افتادن کامل پردازش‌های سرور شود. این موضوع به‌ویژه بر روی سرورهای ابری با منابع محدود (مثلاً سرورهای با ۱ یا ۲ گیگابایت رم) اهمیت دارد.

نوع Worker در Gunicornپروتکل / مکانیزممناسب برای چه سناریویی؟مصرف حدودی رم به ازای هر پردازش
Sync (پیش‌فرض)پردازش مجزا (Process)پروژه‌های معمولی، پردازش‌های محاسباتی (CPU-bound)متوسط تا بالا (۵۰ تا ۱۵۰ مگابایت)
gthreadرشته‌های چندگانه (Threads)پروژه‌های دارای درخواست‌های ورودی/خروجی (I/O-bound)بهینه (اشتراک رم میان Threadها)
Gevent / Eventletناهمگام (Async I/O)وب‌سوکت‌ها، چت‌روم‌ها، تعداد بالای اتصالات معلقبسیار پایین به ازای هر اتصال

فرمول محاسبه تعداد بهینه Workerهای Gunicorn

تعداد بیش از حد Workerها باعث رقابت شدید روی هسته‌های پردازنده و تمام شدن سریع رم می‌شود. طبق مستندات استاندارد، فرمول پایه به شرح زیر است:

$$\text{Workers} = (2 \times \text{CPU Cores}) + 1$$

برای یک سرور با ۲ هسته پردازنده، تعداد مناسب ورکرها برابر با ۵ است:

# اجرای دستی یا در فایل سرویس:
gunicorn --workers 5 --bind unix:/run/gunicorn.sock myproject.wsgi:application

استفاده از مدل ترکیبی Worker و Thread برای کاهش مصرف رم

اگر برنامه شما درخواست‌های خارجی زیادی به APIها یا پایگاه داده ارسال می‌کند (I/O-Bound)، ترکیب Worker و Thread مصرف حافظه را به شدت کاهش می‌دهد:

gunicorn --workers 3 --threads 2 --worker-class gthread --bind unix:/run/gunicorn.sock myproject.wsgi:application

جلوگیری از نشت حافظه (Memory Leaks) با max-requests

پایتون و برخی کتابخانه‌های جانبی ممکن است در پردازش‌های طولانی‌مدت مقداری از رم را آزاد نکنند. با تنظیم پارامترهای زیر، Gunicorn پس از پردازش تعداد مشخصی درخواست، ورکر مربوطه را به صورت روان (Graceful) ریستارت می‌کند:

gunicorn --workers 3 \
         --max-requests 1000 \
         --max-requests-jitter 100 \
         --timeout 30 \
         myproject.wsgi:application
  • max-requests 1000: ورکر پس از هندل کردن ۱۰۰۰ درخواست ریستارت می‌شود.
  • max-requests-jitter 100: اضافه کردن یک عدد تصادفی به سقف درخواست‌ها تا تمام ورکرها به طور هم‌زمان ریستارت نشوند.
  • timeout 30: در صورتی که پردازشی بیش از ۳۰ ثانیه معلق بماند، برای جلوگیری از قفل شدن نخ‌ها متوقف خواهد شد.

برای زیرساخت‌های بزرگ‌تر، پیاده‌سازی این خطوط در قالب CI/CD اهمیت مضاعفی پیدا می‌کند که می‌توانید در مقاله اتوماسیون استقرار و پیاده‌سازی خطوط لوله CI/CD با داکر و گیت‌لب با الگوهای عملیاتی آن آشنا شوید.


۴. چک‌لیست سریع رفع اشکال در محیط پروداکشن

هنگامی که با خطای غیرمنتظره‌ای در سرور روبه‌رو شدید، ترتیب مراحل عیب‌یابی را بر اساس این چک‌لیست پیگیری کنید:

  1. بررسی لاگ‌های Nginx:
    sudo tail -n 50 -f /var/log/nginx/error.log
  2. بررسی لاگ‌های Gunicorn:
    sudo journalctl -u gunicorn -n 50 --no-pager
  3. تست صحت تنظیمات Nginx قبل از ریستارت:
    sudo nginx -t
  4. بررسی پورت‌ها و سوکت‌های فعال:
    sudo ss -tulpn | grep -E '80|443|8000'
  5. بررسی وضعیت دیسک و حافظه رم سرور:
    free -h
    df -h

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


سوالات متداول (FAQ)

۱. تفاوت اصلی بین اجرای Gunicorn با پورت TCP و Unix Socket چیست؟

سوکت یونیکس (.sock) داده‌ها را درون حافظه هسته سیستم‌عامل جابه‌جا می‌کند و سربار بسته‌بندی پروتکل TCP/IP را حذف می‌کند که منجر به سرعت بیشتر و امنیت بالاتر در حالت محلی می‌شود. در مقابل، پورت TCP برای ساختارهای توزیع‌شده یا زمانی که Nginx و Gunicorn روی دو کانتینر یا دو سرور مجزا قرار دارند ضروری است.

۲. چرا پس از تغییر در فایل settings.py یا کدهای جنگو تغییرات اعمال نمی‌شود؟

برخلاف سرور توسعه جنگو (runserver)، Gunicorn کدها را در حافظه لود نگه می‌دارد. پس از هر تغییر در کدهای بک‌اند، باید سرویس Gunicorn را مجدداً راه‌اندازی کنید:

sudo systemctl restart gunicorn

۳. چگونه ارور 413 Request Entity Too Large را در هنگام آپلود فایل رفع کنیم؟

این خطا از سمت Nginx برمی‌گردد. به‌طور پیش‌فرض Nginx حداکثر اندازه بادی درخواست را روی 1MB محدود کرده است. برای تغییر این محدودیت، خط زیر را به بلوک http یا server در فایل کانفیگ Nginx اضافه کنید:

client_max_body_size 20M;

جمع‌بندی

استقرار بدون نقص جنگو نیازمند درک دقیق نحوه تعامل لایه‌های مختلف وب‌سرور، اپلیکیشن‌سرور و هسته لینوکس سرور است. خطای ۵۰۲ با بررسی وضعیت سرویس‌ها و دسترسی به فایل سوکت برطرف می‌شود، لود نشدن استایل‌ها با پیکربندی صحیح مسیرهای استاتیک در Nginx حل خواهد شد و مدیریت درست Workerهای Gunicorn سلامت حافظه RAM سرور شما را تضمین می‌کند.

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