دربارهٔ این فصل
یادداشتِ همراه نوارآیا تا به حال شده که برنامهای در محیط توسعه یا تست شما بینقص کار کند، اما به محض رسیدن به محیط عملیاتی، با مشکلات غیرمنتظرهای روبرو شوید؟ یا شاید در سازمانی کار کردهاید که انتشار یک تغییر کوچک، هفتهها یا ماهها طول میکشد؟ این تجربهها چقدر برایتان آشناست؟
امروز در ادامه بحث از کتاب «فراتر از اپلیکیشن دوازدهعاملی» نوشته «کوین هافمن»، به سراغ چالشهای «همسانی محیطها» و چند مفهوم کلیدی دیگر در طراحی برنامههای بومی ابر میرویم که به ما کمک میکنند تا به عملکرد اپلیکیشنهایمان در هر محیطی اعتماد بیشتری داشته باشیم.
یکی از مهمترین عواملی که شکاف بین محیطها را ایجاد میکند، «زمان» است. در بسیاری از سازمانها، از لحظهای که یک توسعهدهنده کدی را ثبت میکند تا زمانی که آن کد به تولید میرسد، ممکن است هفتهها یا ماهها طول بکشد. این فاصله زمانی طولانی باعث میشود که افراد تغییرات را فراموش کنند و حتی توسعهدهندگان هم از یاد ببرند که کدشان در زمان ثبت چگونه بوده است. راهکار مدرن این است که این فاصله زمانی را از هفتهها و ماهها به دقیقه یا ساعت کاهش دهیم. این کار با استفاده از یک «خط لوله (Pipeline)» استقرار مداوم مناسب انجام میشود که در آن، تغییرات پس از اجرای تستهای خودکار در محیطهای مختلف، به صورت خودکار به تولید منتقل میشوند. شاید این ایده در ابتدا ترسناک به نظر برسد، اما وقتی توسعهدهندگان عادت کنند که کدشان همان روز به تولید میرسد، نظم و کیفیت کد به شدت افزایش مییابد. عامل انسانی هم مهم است: وقتی استقرار به دست افراد انجام میشود، هر فرد ممکن است مراحل را متفاوت اجرا کند؛ خودکارسازی این تفاوتها را کم میکند و هر کامیت را به یک کاندید انتشار تبدیل میکند.
عامل دیگری که به همسانی محیطها آسیب میزند، «منابع» هستند. وقتی برای راهاندازی سریع چیزی عجله داریم، اغلب سازشهایی میکنیم. مثلاً، ممکن است اپلیکیشن ما در تولید به یک پایگاه داده قوی مثل اوراکل نیاز داشته باشد، اما برای توسعه محلی، از یک پایگاه داده در حافظه استفاده کنیم. هر بار که چنین سازشی میکنیم، شکاف بین محیطهای توسعه و تولید را افزایش میدهیم و هر چه این شکاف بیشتر باشد، پیشبینیپذیری رفتار اپلیکیشن کمتر میشود و قابلیت اطمینان آن کاهش مییابد. امروزه ابزارهای زیادی در دسترس توسعهدهندگان است. میتوان از همان نوع «سرویس پشتیبان (Backing service)» در همه محیطها استفاده کرد، یا ابزارهایی مانند داکر (Docker) به ایجاد محیطهای شبیه تولید روی ایستگاههای کاری توسعهدهندگان کمک میکنند. هر تصمیمی که شکاف عملکردی بین محیطهای استقرار شما را افزایش میدهد، باید مورد سؤال قرار گیرد و باید در برابر وسوسه تفاوت قائل شدن بین محیطها مقاومت کرد.
حالا به سراغ «فرایندهای مدیریتی (Admin process)» میرویم. این فرایندها کارهای یکباره یا نگهداری هستند که جدا از فرایند اصلی اپلیکیشن اجرا میشوند. توصیه اصلی اپلیکیشن دوازدهعاملی این بود که این کارها به عنوان فرایندهای یکباره اجرا شوند، اما کوین هافمن معتقد است که این توصیه میتواند گمراهکننده باشد. مشکل اینجاست که استفاده از زمانبندهای خارجی مثل کرون (Cron) یا حتی اجرای اسکریپتهای تعاملی، در محیط ابری میتواند منجر به هرج و مرج و خطاهای دادهای شود، به خصوص وقتی چندین نمونه از اپلیکیشن در حال اجرا هستند. مثلاً، اگر یک کار دستهای شبانه را با یک زمانبند داخلی در هر نمونه از اپلیکیشن اجرا کنید، ممکن است این کار چندین بار اجرا شود و دادهها را خراب یا تکراری کند.
برای حل این مشکل، راهحلهای بهتری وجود دارد. یکی از جذابترین آنها، این است که قابلیتهای موقت و مدیریتی را از طریق یک «پایانه REST (REST endpoint)» در اپلیکیشن خود ارائه دهید. این کار به شما اجازه میدهد که این قابلیتها را به صورت کنترلشده و امن فراخوانی کنید. راهکار دیگر این است که کد مربوط به کارهای دستهای را از اپلیکیشن اصلی جدا کرده و به یک «میکروسرویس (Microservice)» جداگانه تبدیل کنید. این میکروسرویس میتواند به صورت مستقل مقیاسپذیر باشد و از مزایای دیگر ابر نیز بهرهمند شود. حتی میتوانید از توابع بومی ابر مانند AWS Lambda استفاده کنید که فقط در صورت نیاز فراخوانی میشوند و نیازی به سرورهای همیشه روشن ندارند.
در نهایت، به «اتصال پورت (Port binding)» میرسیم. اپلیکیشنهای بومی ابر باید سرویسهای خود را از طریق اتصال پورت ارائه دهند. در محیطهای غیرابری، به خصوص در سازمانهای بزرگ، معمولاً چندین اپلیکیشن در یک «کانتینر (Container)» سرور وب میزبانی میشوند و با شماره پورتهای مختلف از هم جدا میشوند. این کار مدیریت پورتها را پیچیده میکند. اما در محیط ابری، ارائهدهنده خدمات ابری مسئولیت مدیریت پورتها، مسیریابی، مقیاسگذاری و دسترسی بالا را بر عهده دارد.
و در نهایت، فصل دوازدهم به «فرایندهای بیحالت (Stateless Processes)» میپردازد. یک فرایند بیحالت هیچ فرضی دربارهٔ محتوای حافظه پیش یا پس از پردازش درخواست ندارد؛ میتواند در میانهٔ کار وضعیت موقت بسازد، اما پس از پاسخ دادن، آن وضعیت باید از بین برود. هر وضعیت ماندگار باید به یک سرویس پشتیبان مثل پایگاه داده منتقل شود. به همین دلیل، یک میکروسرویس مدیریت کاربران بیحالت است و فهرست کاربران در پایگاه داده نگهداری میشود. هافمن الگوی «هیچچیز مشترک (Share-Nothing)» را هم توصیه میکند: هر دادهٔ مشترک بین فرایندها یک نقطهٔ شکست است، و چون فرایندها در ابر هر لحظه ممکن است حذف یا جابهجا شوند، اشتراک وضعیت میتواند باعث شکست زنجیرهای شود. حتی فایلسیستم هم سرویس پشتیبان محسوب نمیشود.