نگاهی به Muru؛ اجرای برنامه‌های Python با مدل مشترک توسعه و production

چرا مهم است

اگر برنامه وب Python داری، تفکیک queue و app در Muru به تو نشان می‌دهد درخواست کجا معطل شده است. متن میان کندی اجرای برنامه و انتظار برای آزادشدن thread تفاوت می‌گذارد؛ دو مسئله‌ای که بررسی متفاوتی می‌خواهند.

قبل از خواندن، این‌ها را بدان۴ مفهوم
WSGI

استاندارد ارتباط میان برنامه وب Python و server است که نحوه دریافت درخواست و برگرداندن پاسخ را مشخص می‌کند.

بیشتر درباره این مفهوم

virtual environment

محیطی جدا برای Python و package‌های یک پروژه است تا dependency‌های آن از محیط‌های دیگر مستقل بمانند.

بیشتر درباره این مفهوم

callable

شیئی در Python که می‌توان آن را مانند یک function فراخوانی کرد.

بیشتر درباره این مفهوم

fork

روشی برای ساخت process جدید از روی process موجود است؛ process جدید در آغاز نسخه‌ای از وضعیت process قبلی را دارد.

بیشتر درباره این مفهوم

Graham Dumpleton در معرفی عملی Muru، حالت توسعه این ابزار را با یک برنامه ساده WSGI نشان می‌دهد. Muru سه شیوه اجرا دارد: حالت توسعه روی دستگاه شخصی، daemon برای میزبانی روی server و اجرا در container. هر سه از یک process model استفاده می‌کنند. این ابزار هنوز در مرحله alpha است و روی Linux و macOS از CPython 3.11 به بعد، از جمله build‌های free-threaded، پشتیبانی می‌کند.

Muru دو بخش دارد: دستور muructl یک binary نوشته‌شده با Rust است که خودش dependency مربوط به Python ندارد؛ بخش دوم، muru، یک runtime است که داخل interpreter برنامه اجرا می‌شود. muructl در نخستین اجرا برای هر نسخه Python، runtime متناسب را دریافت و در cache کاربر ذخیره می‌کند؛ چیزی داخل پروژه نصب نمی‌شود. نصب با uv tool install muructl، همچنین با pipx یا pip امکان‌پذیر است.

برای اجرای نمونه، دستور muructl run app:application نام module و callable را می‌گیرد. فعال‌کردن virtual environment لازم نیست؛ muructl پوشه .venv را پیدا می‌کند. ابتدا host برنامه را import می‌کند و سپس worker با fork از آن ساخته می‌شود؛ در نتیجه برنامه از قبل در worker بارگذاری شده است. بخش edge اتصال‌های HTTP را می‌پذیرد و درخواست‌ها را به worker می‌فرستد. Muru پیش از fork، هنگام import بررسی می‌کند که مواردی مانند بازشدن اتصال database یا شروع thread پس‌زمینه رخ داده‌اند یا نه؛ نویسنده جزئیات این بررسی را به مطلب دیگری موکول کرده است.

در access log، مقدار queue زمان انتظار برای آزادشدن یک worker thread و مقدار app زمان اجرای برنامه را نشان می‌دهد. این تفکیک مشخص می‌کند تأخیر ناشی از اجرای برنامه است یا مشغول‌بودن همه thread‌ها. هر درخواست شناسه‌ای دارد که در header با نام X-Request-ID هم برگردانده می‌شود تا پاسخ با log تطبیق داده شود.

حالت توسعه فقط روی loopback گوش می‌دهد و برای دسترسی بیرونی نیست. هنگام exception، traceback در پاسخ خطا و terminal نمایش داده می‌شود؛ درخواست JSON نیز پاسخ application/problem+json می‌گیرد. این exception درخواست را ناموفق می‌کند، نه اینکه worker را از بین ببرد.

با تغییر فایل Python، reload خودکار یک host و worker جدید کنار نمونه قبلی می‌سازد. تنها پس از آماده‌شدن worker جدید، ترافیک به آن منتقل و نمونه قبلی خاموش می‌شود. هر مجموعه host و worker یک release شماره‌دار است.

نکته کلیدی

برای امتحان‌کردن Muru، حالت توسعه را با اجرای production یکی نگیر: این حالت فقط روی loopback گوش می‌دهد و traceback را نمایش می‌دهد. هنگام خواندن log هم زمان queue را جدا از app بررسی کن.

خواندن مقاله اصلی (در زبانه‌ی جدید باز می‌شود)
برچسب‌ها (۳)