آشنایی با ۱۲-فاکتور اپلیکیشن (The twelve-factor app) فاکتور های هفتم تا دهم

دوازده فاکتور اپلیکیشن
دوازده فاکتور اپلیکیشن - صادق خان

با سلام و درود، با قسمت سوم از آشنایی با فاکتورهای ۱۲ گانه اپلیکیشن در خدمتتان هستم (۱۲-فاکتور اپلیکیشن یا The twelve-factor app ) . در قسمت اول با فاکتور های اول چهارم و در قسمت دوم با فاکتورهای چهارم تا ششم آشنا شدیم که به شرح زیر بودند:

فاکتور اول: codebase – پایگاه کد

یک codebase در کنترل revision ردیابی می شود و بسیاری از آنها مستقر (deploy) می شوند.

به طور خلاصه، یه کدبیس خواهیم داشت و همان را در چند جا مستقر می کنیم.

فاکتور دوم: Dependencies – وابستگی ها

به صورت صریح . ایزوله، dependency ها مشخص می شوند

فاکتور سوم: config – کانفیگ

کانفیگ در محیط هر استقرار نگه داری شود، ترجیحا از متغیرهای محیط استفاده شود.

برای مطالعه کامل تر روی ۳ فاکتور نخست از فاکتورهای دوازده گانه اپلیکیشن، پیشنهاد می کنم قسمت اول ( آشنایی با ۱۲-فاکتور اپلیکیشن (The twelve-factor app) فاکتور های اول تا سوم ) از این مطلب را حتما نگاه بندازید.

فاکتور چهارم: Backing services -سرویس های پشتی

خدمات پشتیبان، به عنوان منابع پیوستی تلقی شوند.

فاکتور پنجم: Build, release, run ، ساخت، انتشار، اجرا

مراحل ساخت و اجرا را کاملا جدا کنید

فاکتور ششم: Processes -فرآیندها

app را به عنوان یک یا چند فرآیند بدون حالت (stateless) اجرا کنید.

برای مطالعه کامل تر روی فاکتور های چهارم الی هفتم از فاکتورهای دوازده گانه اپلیکیشن، پیشنهاد می کنم قسمت دوم ( آشنایی با ۱۲-فاکتور اپلیکیشن (The twelve-factor app) فاکتور های چهارم تا تا هفتم ) از این مطلب را حتما نگاه بندازید.

در ادامه به فاکتورهای هفتم الی دهم می پردازیم.

فاکتور هفتم: Port bindinge

export کردن سرویس ها را با استفاده از Port Binding انجام دهید.

برنامه های وب گاهی اوقات در داخل یک کانتینر وب سرور اجرا می شوند. به عنوان مثال، برنامه های PHP ممکن است به عنوان یک ماژول در Apache HTTPD اجرا شوند، یا برنامه های جاوا ممکن است در داخل Tomcat اجرا شوند.

اپلیکیشن ۱۲ عاملی، به صورت کامل مستقل است، و برای ایجاد یک سرویس web-facing متکی بر runtime injection از یک وبسرور به درون محیط اجرا نمی باشد. برنامه وب HTTP را به عنوان یک سرویس با اتصال به یک پورت (binding to port) و گوش دادن به درخواست هایی که در آن پورت وارد می شود صادر می کند.

در محیطز های توسعه لوکال، توسعه دهنده یک سرویس را با URLمشابه http://localhost:5000/ می بیند تا به سرویس export شده توسط appشان دسترسی داشته باشد. در استقرار (deployment) یک لایه مسیر یابی (routing layer) به مدیریت مسیریابی request ها از یک hostname به فرآیند های وب متصل به port می پردازد.

این عمل معمولا با استفاده از اعلان یک وابستگی (dependency) جهت افزودن کتابخانه های webserver به app پیاده سازی می شود، مانند Tornado برای Python یا Thin برای Rubyیا Jettyبرای Java. این کار به طور کامل در فضای کاربر اتفاق می افتد.قرارداد با محیط اجرا، اتصال به یک port جهت ارائه requestها می باشد.

HTTP تنها سرویسی نیست که باید باید توی اتصال به port صادر (export) شود. تقریبا هر نوع نرم افزار سروری را می توان توسط اتصال به پورت و منتظر request دریافتی بودن، اجرا کرد.

نکته مهم اینجاست و توجه داشته باشید که با استفاده از Port Binding، یک app می تواند، سرویس پشتیبان یک app دیگر باشد.

فاکتور هشتم: Concurrency – همزمانی

توسط مدل فرآیند، مقیاس پذیر کنید

هر appکامپیوتری، پس از اجرا، توسط یک یا چند فرآیند نمایش داده می شود. اپلیکیشن های Web ، شکل های مختلفی از فرآیند را برای اجرا به کار می گیرند. برای مثال، فرآیند های PHPبه عنوان فرزندی از فرآیند های Appache اجرا می شوند و بر حسب حجم درخواست شروع می شوند.

در app های ۱۲ عاملی، فرآیند ها شهروند درجه اول هستند. فرآیند های موجود در appهایی با فاکتورهای دوازدهگانه، نشانه های قوی ای از مدل فرآیند یونیکس برای اجرای Service daemon ها می گیرند. با ساتفاده از این مدل، توسعه دهنده می تواند برنامه خود را برای مدیریت بار های کاری مختلف با اختصاص هر نوع کار به یک نوع فرآیند، طراحی کند. به عنوان مثال: request های HTTP ممکن است توسط یک فرآیند وب مدیریت شود و taskهای long-running background توسط فرآیند های workerمدیریت شوند.

این امر فرآیندهای منفرد را از مدیریت مالتی پلکس داخلی خود، از طریق رشته‌های داخل VM زمان اجرا، یا مدل async/evented که در ابزارهایی مانند EventMachine، Twisted یا Node.js یافت می‌شود، مستثنی نمی‌کند. اما یک ماشین مجازی تنها می‌تواند تا این اندازه بزرگ شود (مقیاس عمودی)، بنابراین برنامه باید بتواند چندین فرآیند در حال اجرا بر روی چندین ماشین فیزیکی را نیز بپوشاند.

زمانی که زمان بزرگ‌نمایی فرا می‌رسد، مدل فرآیند واقعاً می‌درخشد. ماهیت اشتراک‌گذاری هیچ و قابلیت پارتیشن افقی فرآیندهای برنامه دوازده عاملی به این معنی است که افزودن همزمانی بیشتر یک عملیات ساده و قابل اعتماد است. آرایه انواع فرآیند و تعداد فرآیندهای هر نوع به نام تشکیل فرآیند شناخته می شود.

فرآیندهای برنامه دوازده عاملی هرگز نباید فایل های PID را daemonize کنند یا بنویسند. در عوض، برای مدیریت جریان‌های خروجی، پاسخگویی به فرآیندهای خراب و مدیریت راه‌اندازی مجدد و خاموش شدن توسط کاربر، به مدیر فرآیند سیستم‌عامل (مانند systemd، مدیر فرآیند توزیع‌شده در پلتفرم ابری یا ابزاری مانند Foreman در حال توسعه) تکیه کنید.

فاکتور نهم: Disposability – یکبار مصرف

با راه‌اندازی سریع و خاموش شدن برازنده، استحکام (robustness) را به حداکثر برسانید

فرآیندهای برنامه دوازده عاملی یکبار مصرف هستند، به این معنی که می توان آنها را در یک لحظه شروع یا متوقف کرد. این مقیاس سریع الاستیک، استقرار سریع کد یا تغییرات پیکربندی، و استحکام استقرار تولید را تسهیل می‌کند.

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

فرآیندها با دریافت سیگنال SIGTERM از مدیر فرآیند، به طور برازنده و خوب خاموش می شوند. برای یک فرآیند وب، با توقف گوش دادن به درگاه سرویس (در نتیجه رد هر درخواست جدید)، اجازه دادن به تمام درخواست‌های فعلی و سپس خروج، خاموش شدن برازنده به دست می‌آید. ضمناً در این مدل درخواست‌های HTTP کوتاه هستند (بیش از چند ثانیه نیستند)، یا در مورد نظرسنجی طولانی، کلاینت باید زمانی که اتصال قطع شده است، به طور یکپارچه برای اتصال مجدد تلاش کند.

برای یک فرآیند کارگر (worker process)، با برگرداندن کار فعلی به صف کار، خاموشی دلپذیر حاصل می شود. به عنوان مثال، در RabbitMQ کارگر می تواند یک NACK ارسال کند. در Beanstalkd، هر زمان که یک کارگر ارتباط خود را قطع کند، کار به طور خودکار به صف باز می گردد. سیستم های مبتنی بر قفل مانند Delayed Job باید مطمئن شوند که قفل خود را در سابقه کار آزاد کنند.

ضمناً در این مدل همه jobs مجدداً وارد می شوند، که معمولاً با قرار دادن نتایج در یک تراکنش یا عدم توانایی عملیات به دست می آید.

فرآیندها همچنین باید در برابر مرگ ناگهانی، در صورت خرابی سخت افزار زیرین، قوی باشند. در حالی که این اتفاق بسیار کمتر از یک خاموشی برازنده با SIGTERM است، اما هنوز هم ممکن است اتفاق بیفتد. یک رویکرد توصیه شده استفاده از یک backend صف قوی (robust queueing backend)، مانند Beanstalkd است، که در صورت قطع اتصال کلاینت ها یا اتمام زمان، کارها را به صف برمی گرداند. در هر صورت، یک برنامه دوازده عاملی برای مدیریت خاتمه های غیرمنتظره و غیر برازنده طراحی شده است.