Muru؛ یک‌بار import و چندین fork،؜ با بررسی ایمنی برنامه

چرا مهم است

اگر برنامه‌ات هنگام import اتصال database باز می‌کند یا thread راه می‌اندازد، preloading می‌تواند worker‌ها را دچار مشکل کند. بررسی Muru این منابع را گزارش می‌کند و در صورت نیاز به import جداگانه برمی‌گردد.

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

ساخت یک process فرزند از process موجود؛ فرزند با نسخه‌ای از وضعیت حافظه والد شروع می‌کند، اما همه منابع بیرونی مانند thread و اتصال‌ها لزوماً به شکل مستقل در اختیارش قرار نمی‌گیرند.

بیشتر: fork

preloading

بارگذاری برنامه پیش از ساخت worker‌ها؛ در الگوی مبتنی بر fork،؜ worker‌ها با module‌های ازپیش‌بارگذاری‌شده شروع می‌کنند.

در حال نگارش: preloading

hook

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

در حال نگارش: hook

Graham Dumpleton در مطلبی درباره Muru توضیح می‌دهد که این ابزار چگونه برنامه Python را یک‌بار در process میزبان یا host بارگذاری می‌کند و سپس worker‌ها را از آن fork می‌کند. در نمونه‌ای با دو worker،؜ شناسه process زمان import برای هر دو یکسان است، اما هر درخواست در process یکی از worker‌ها پاسخ می‌گیرد؛ یعنی worker‌ها خودشان برنامه را دوباره import نکرده‌اند.

این روش که preloading نام دارد، برای برنامه بزرگی مثل یک برنامه Django اهمیت دارد؛ چون import همه بخش‌ها می‌تواند چند ثانیه زمان و حافظه زیادی بخواهد. worker‌های حاصل از fork،؜ صفحه‌های حافظه حاوی module‌ها را تا زمانی که چیزی در آن‌ها نوشته نشود، با host و یکدیگر به اشتراک می‌گذارند. ساخت worker جایگزین یا اضافه نیز به‌جای import کامل، به یک fork نیاز دارد. Muru پیش از fork،؜ دید garbage collector نسبت به object‌های ازپیش‌بارگذاری‌شده را freeze می‌کند تا فعالیت آن در worker‌ها باعث دست‌خوردن و کپی‌شدن این صفحه‌ها نشود.

اما همه منابع با fork سازگار نیستند. socket یک object در kernel است و پس از fork،؜ والد و فرزند همان اتصال را در اختیار دارند. thread پس‌زمینه‌ای که هنگام import شروع شده، در worker‌ها وجود ندارد، هرچند ساختارهای داده‌اش کپی شده‌اند. worker‌ها همچنین نمی‌توانند یک process کمکی را که host ساخته، مدیریت کنند. بنابراین بازکردن اتصال database یا شروع thread هنگام import می‌تواند مشکل‌هایی ایجاد کند که زیر بار کاری آشکار می‌شوند.

Muru هنگام import،؜ socket،؜ pipe،؜ thread و process فرزندی را که باقی مانده‌اند ثبت می‌کند. در نمونه اتصال database،؜ ابزار socket باز را تشخیص می‌دهد، محل اتصال را گزارش می‌کند و به import جداگانه برنامه در هر worker برمی‌گردد. برنامه همچنان کار می‌کند، اما مزیت حافظه مشترک و جایگزینی سریع‌تر worker را از دست می‌دهد. نمونه thread گزارش‌دهی نیز به همین شکل شناسایی می‌شود.

برای انتقال این کارها به زمان مناسب، Muru از hook پشتیبانی می‌کند. module مربوط به hook با گزینه --hooks یا تنظیم hooks در بخش [tool.muru] مشخص می‌شود. تابع post_fork بلافاصله پس از fork در هر worker اجرا می‌شود. در نمونه مطلب، شروع thread از زمان import به این hook منتقل می‌شود تا هر worker،؜ thread خودش را داشته باشد. هر hook نیز یک object به نام context می‌گیرد که اطلاعات محل اجرا، از جمله شماره worker،؜ را در اختیارش می‌گذارد.

نکته کلیدی

شروع thread را از زمان import به post_fork منتقل کن تا هر worker آن را جداگانه بسازد. برای اتصال باز هم پیام Muru را بررسی کن: بستن در pre_fork و بازکردن در post_fork،؜ یا بازکردن هنگام اولین استفاده پیشنهاد شده است.

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