پروژه Django روی لپتاپ عالی اجرا میشه، با python manage.py runserver بالا میاد و حتی چند نفر هم بدون مشکل وارد سایت میشن. همینجا یه اشتباه رایج شکل میگیره: «خب وقتی داره کار میکنه، چرا روی سرور واقعی هم همین دستور رو اجرا نکنیم؟»
مشکل اینه که runserver برای راحتی برنامهنویس هنگام توسعه ساخته شده، نه برای اینکه ماهها زیر ترافیک واقعی اینترنت روشن بمونه. چیزی که روی سیستم شخصی کاملاً مناسب به نظر میرسه، وقتی سایت کاربر واقعی، ترافیک همزمان و خطاهای غیرمنتظره داشته باشه دیگه انتخاب مناسبی نیست.
runserver دقیقاً برای چه کاری ساخته شده؟
وقتی پروژه Django رو توسعه میدید، به یه سرور ساده نیاز دارید که سریع بالا بیاد، تغییر فایلها رو تشخیص بده و بعد از تغییر کد خودش دوباره اجرا بشه. runserver دقیقاً همین کار رو انجام میده.
این سرور برای محیط توسعه طراحی شده؛ یعنی جایی که برنامهنویس داره کد رو میسازه و تست میکنه.
اما محیط واقعی اجرای سایت برای کاربران رو معمولاً با اصطلاح Production میشناسیم. توی این محیط موضوع فقط بالا اومدن سایت نیست؛ پایداری، مدیریت درخواستهای همزمان، Restart شدن بعد از خطا، امنیت و استفاده درست از منابع سرور اهمیت پیدا میکنه.
پس روی سرور واقعی چی باید Django رو اجرا کنه؟
بین وبسرور و برنامه Django معمولاً یه نرمافزار مخصوص اجرای برنامه پایتون قرار میگیره. این نرمافزار درخواستها رو دریافت میکنه و اونها رو به Django تحویل میده.
یکی از معروفترین گزینهها برای پروژههای معمولی Django، Gunicorn هست.
Gunicorn میتونه چند پردازش جدا برای پاسخ دادن به کاربران اجرا کنه. به این پردازشهای اجراکننده معمولاً Worker گفته میشه. یعنی اگر یه Request درگیر کاری بشه، کل برنامه الزاماً به همون یک مسیر اجرا وابسته نیست.
یه اجرای ساده میتونه به این شکل باشه:
gunicorn myproject.wsgi:application --workers 3 --bind 127.0.0.1:8000
اینجا به Gunicorn گفتیم برنامه Django رو اجرا کنه و سه Worker برای پاسخ دادن به درخواستها داشته باشه.
این فقط یه نمونه سادهست و تعداد Workerها باید با توجه به CPU، حافظه و نوع پروژه تنظیم بشه؛ عدد ۳ قانون همیشگی نیست.
WSGI یعنی چی؟
Django باید یه روش استاندارد داشته باشه تا بتونه با سروری مثل Gunicorn صحبت کنه.
روش قدیمیتر و بسیار رایج این ارتباط برای برنامههای وب پایتون، رابط استاندارد بین وبسرور و برنامه پایتون هست که اسم انگلیسی اون WSGI ـه.
برای سایتهای معمولی Django که بیشتر Request دریافت میکنن، با دیتابیس کار میکنن و Response برمیگردونن، WSGI همچنان انتخاب کاملاً مناسبیه.
به همین دلیله که داخل پروژه Django فایلی به اسم wsgi.py هم میبینید.
پس Uvicorn برای چیه؟
مدل جدیدتری هم وجود داره که علاوه بر درخواستهای عادی، برای ارتباطهای طولانیتر و قابلیتهای غیرهمزمان مناسبتره. به این رابط استاندارد غیرهمزمان اجرای برنامههای پایتونی گفته میشه که اسمش ASGI هست.
Uvicorn یکی از سرورهایی هست که برنامههای مبتنی بر ASGI رو اجرا میکنه.
اگه پروژه Django شما قابلیتهایی مثل WebSocket، ارتباط زنده، بعضی پردازشهای Async یا اتصالهای طولانی داره، ASGI و Uvicorn میتونن انتخاب مناسبتری باشن.
Django برای همین حالت هم فایل asgi.py داره.
یعنی Gunicorn قدیمیه و باید همیشه Uvicorn استفاده کنیم؟
نه.
انتخاب بین این دوتا به نوع پروژه بستگی داره، نه اینکه کدوم اسم جدیدتر یا جذابتره.
اگه یه سایت فروشگاهی، شرکتی، خبری یا API معمولی دارید، Gunicorn میتونه کاملاً نیازتون رو برطرف کنه. اگه قابلیتهای غیرهمزمان و ارتباطهای زنده دارید، اون موقع Uvicorn و ASGI اهمیت بیشتری پیدا میکنن.
حتی میشه بعضی معماریها رو طوری تنظیم کرد که Gunicorn مدیریت Workerها رو انجام بده و Workerهای ASGI برنامه رو اجرا کنن.
Nginx کجای داستان قرار میگیره؟
یه سؤال رایج اینه که اگه Gunicorn یا Uvicorn داریم، پس Nginx برای چیه؟
Nginx معمولاً جلوی برنامه قرار میگیره. یعنی کاربر مستقیماً با Gunicorn ارتباط برقرار نمیکنه و Request ابتدا به Nginx میرسه.
Nginx میتونه فایلهای ثابت مثل CSS، JavaScript و تصاویر رو تحویل بده، ارتباط HTTPS رو مدیریت کنه و Requestهای لازم رو به برنامه Django بفرسته.
به این مدلی که یه سرور جلوی برنامه قرار میگیره و درخواست رو به سرور داخلی منتقل میکنه، واسط معکوس بین کاربر و برنامه گفته میشه که اصطلاح انگلیسی اون Reverse Proxy هست.
یه معماری رایج در نتیجه چیزی شبیه این میشه:
کاربر ← Nginx ← Gunicorn یا Uvicorn ← Django
چرا Restart شدن برنامه مهمه؟
روی سیستم خودتون اگه Django Crash کنه، ترمینال رو باز میکنید و دوباره اجراش میکنید. روی سایت واقعی نمیشه منتظر موند تا یکی متوجه بشه سایت پایین اومده.
برای همین معمولاً یه ابزار مدیریت سرویس مثل systemd یا ابزار مشابه روی سرور تنظیم میشه تا برنامه رو اجرا کنه و اگه Process متوقف شد، دوباره اون رو بالا بیاره.
پس اجرای حرفهای Django فقط انتخاب Gunicorn نیست؛ باید کل چرخه اجرای برنامه مدیریت بشه.
Debug هم نباید روی سرور واقعی روشن باشه
یکی دیگه از تفاوتهای مهم محیط توسعه و Production تنظیم DEBUG هست.
هنگام توسعه، DEBUG=True خیلی مفیده چون Django اطلاعات دقیق خطا رو نشون میده. اما همین اطلاعات روی اینترنت میتونه جزئیات داخلی پروژه، مسیر فایلها و اطلاعات فنیای رو نمایش بده که کاربر عادی نباید ببینه.
پس روی سرور واقعی معمولاً باید DEBUG=False باشه و تنظیماتی مثل ALLOWED_HOSTS، فایلهای Static، HTTPS و Logging هم درست پیکربندی بشن.
آیا runserver برای دو سه کاربر هم خطرناکه؟
بحث اصلی تعداد دقیق کاربران نیست. ممکنه runserver حتی برای چند کاربر هم ظاهراً بدون مشکل کار کنه، ولی مسئله اینه که برای شرایط واقعی و قابل اتکا طراحی نشده.
ممکنه سایت امروز با پنج کاربر کار کنه و شما فکر کنید همهچیز خوبه، ولی این دلیل نمیشه معماری مناسبی برای نگهداری سرویس واقعی داشته باشید.
بهتره از همون زمان Deploy، ابزار مناسب Production رو انتخاب کنید تا بعداً مجبور نشید وسط رشد پروژه نحوه اجرای کل سرویس رو تغییر بدید.
جمع بندی
python manage.py runserver ابزار فوقالعادهای برای توسعه Django هست، ولی وظیفهش همینجاست. وقتی پروژه قراره روی سرور واقعی و در اختیار کاربران قرار بگیره، بهتره از سروری استفاده کنید که برای اجرای پایدار برنامههای پایتونی ساخته شده.
برای پروژههای معمولی Django، ترکیب Nginx + Gunicorn انتخاب رایج و سادهایه. اگه پروژه به WebSocket یا قابلیتهای غیرهمزمان نیاز داره، Uvicorn و ASGI هم وارد ماجرا میشن.
مهمترین نکته اینه که «سایت بالا میاد» با «سایت برای Production درست Deploy شده» دو چیز متفاوتن. runserver اولی رو انجام میده؛ برای دومی باید یه قدم حرفهایتر جلو برید.
نظرات کاربران (0)