مهاجرت از دنیای برنامهنویسی یکپارچه بهسمت میکروسرویسها
آماده هستید از استراتژیهای سنتی توسعه نرمافزارهای کاربردی بهسمت پارادایم قدرتمند میکروسرویسها مهاجرت کنید؟ پیشنهاد ما این است که شتابزده کار نکنید و بر مبنای برنامه راهبردی معرفیشده در این مقاله گام بردارید تا بتوانید بهتدریج از استراتژی توسعه یکپارچه بهسمت طراحی میکروسرویس گام بردارید.
معماری میکروسرویس با ارائه قابلیتهای کاربردی مثل مقیاسبندی انعطافپذیر، بهروزرسانی ویژگیهای مستقل و اجرای کارهای تخصصی توسط ماژولهای کوچک، به توسعهدهندگان زمان کافی برای کار روی ماژولها را میدهد. با اینحال، هنوز هم برخی تیمها بهدلیل عدم آشنایی دقیق با این پارادایم ترجیح میدهند از پارادایمهای قدیمی توسعه استفاده کنند که هزینههای جانبی ساخت و استقرار نرمافزارها را افزایش میدهند. بهطور معمول، برنامههای قدیمی عمدتا بر مبنای معماری یکپارچه توسعه پیدا کردهاند. همچنین، هنگامی که تیمهای نرمافزاری تصمیم میگیرند کار روی یک برنامه کاربردی را آغاز کنند، ترجیح میدهند از همان ابتدا به سراغ معماری یکپارچه بروند.
نرمافزارهای مبتنی بر معماری یکپارچه ساختار تقریبا سادهای دارند، اما تنها در ابتدای فرآیند توسعه این مسئله صادق است. بهطور مثال، مهندسان بخش Google Cloud هنگامی که تصمیم گرفتند روی فرآیند توسعه درون سازمان فناوری کلاد برای دو واحد داخلی گوگل کار کنند، تصمیم گرفتند از معماری یکپارچه برای تسریع در روند ساخت استفاده کنند، اما گذشت زمان نشان داد که حفظ و مدیریت حجم عظیمی از کدها پیچیده، سخت و زمانبر است و بهتدریج که حجم کدها افزایش پیدا میکرد، پیچیدگی دوچندان میشد. علاوه بر این، فرآیند نگهداری از کدها به این دلیل سخت و زمانبر بود که توسعهدهندگان جدیدی که به تیم افزوده میشدند، مجبور بودند تمامی کدها را بررسی کنند تا منطق و عملکرد کدها را درک کنند.
مهاجرت به دنیای توسعه مبتنی بر میکروسرویسها، مرزبندی مشخصی بین ویژگیهای یک برنامه کاربردی، بهروزرسانیهای سادهتر در گذر زمان و اعمال تغییرات بدون تاثیرگذاری بر عملکرد سایر بخشهای یک برنامه را امکانپذیر میکنند.
با اینحال، برای آنکه بتوانید یک برنامه یکپارچه را به میکروسرویس تبدیل کنید، ضروری است بر مبنای یک برنامه جامع گام بردارید و کار را با کدهای منبع و پشته فناوری آغاز کنید. در ادامه، با تمرکز بر مکانیزم ارتباطی بین سرویسها و اتخاذ تمهیدات لازم برای مقابله با خرابیها، فرآیند توسعه سرویسها و ماژولهای میکروسرویسها را آغاز کنید.
برنامهریزی برای مهاجرت
قبل از شروع مهاجرت به دنیای میکروسرویسها، ابتدا وضعیت را ارزیابی کنید تا بتوانید یک برنامه راهبردی مناسب را اتخاذ کنید. برای این منظور، چند نکته کلیدی مهم وجود دارد که باید به آنها دقت کنید.
تمرکز بر جزئیات موردنیاز در سرویسها
هنگامی که قصد شکستن یک معماری واحد نرمافزاری به بخشهای کوچکتر را دارید، میتوانید چند سرویس کوچک یا چند سرویس بزرگ ایجاد کنید. در اینجا، خطمشی صریح و مشخصی وجود ندارد. نکته مهمی که باید به آن دقت کنید این است که هر سرویس اندازه مناسبی داشته باشد، زیرا هرچه تعداد سرویسها بیشتر باشد، هزینه و پیچیدگی افزایش پیدا میکنند. با این حال، اگر سرویسها بیشازحد بزرگ باشند، با مشکل عدم برقراری ارتباط درست مولفهها با یکدیگر و عدم بهروزرسانی درست و بهموقع ویژگیهای مستقل روبهرو هستید. بهترین راهکار در این زمینه این است که کد منبع برنامه و اسناد مرتبط با طراحی را مرور کنید تا بتوانید بهشکل سادهتری سرویسها را از هم جدا کنید و بتوانید مستندات دقیقی برای هر یک از سرویسها بنویسید. برای تسهیل همکاری بین تیمها، مخازن مربوط به سورسکدهای سرویسها را بهاشتراک قرار دهید و به تیمها اجازه دهید بر مبنای یک راهکار ساده به کدها دسترسی داشته باشند.
از یک پشته فناوری متنوع استفاده کنید
میکروسرویسها به معماری مشخصی نیاز دارند که توانایی جداسازی بخش فرانتاند یک برنامه کاربردی از زیرساخت بکاند را داشته باشد. بر همین اساس، بهتر است از رویکرد توسعه چندزبانی استفاده کنید. بهطوریکه از زبانهای برنامهنویسی مناسبی برای توسعه هر سرویس استفاده کنید. بهطور مثال، چارچوبی مثل Polymer را در نظر بگیرید که امکان میدهد مولفههای مختلف فرانتاند را بهطور مستقل مدیریت کنید.
مهاجرت واقعی
برای آنکه مهاجرت دقیق و حسابشدهای از دنیای یکپارچه به میکروسرویس داشته باشید باید از تکنیکهایی برای تجزیه تدریجی کدهای یکپارچه استفاده کنید. بهطور مثال، مهندسان گوگل از الگوی Strangler استفاده میکنند. سازوکار مکانیزم فوق به این صورت است که یک پروکسی برای هدایت ترافیک بهسمت معماری یکپارچه تعریف میشود. در ادامه، تیم روی توسعه سادهترین بخشهای معماری یکپارچه متمرکز میشوند و بهتدریج به سراغ بخشهای پیچیده میروند. همانطور که سرویسها یکبهیک ساخته میشوند، ترافیک بهشکل پلکانی برای میکروسرویسهای جدید ارسال میشوند. استراتژی مذکور، اختلال در عملکرد کاربران را بهحداقل میرساند و به معمار و توسعهدهندگان معماری یکپارچه فرصت کافی برای مهاجرت به معماری میکروسرویسها و بازسازی نرمافزارها را میدهد.
اجرای مکانیزمهای نظارتی
مهاجرت به دنیای میکروسرویسها بدون استفاده از راهکاری موثر برای نظارت و مدیریت بر برنامه کاربردی، منطقی نیست. بهطور مثال، عدم برقراری ارتباط درست میکروسرویسها باعث میشود تا برنامه عکسالعملهای غیرمنتظرهای از خود نشان دهد و مجبور شوید زمان زیادی را صرف شناسایی لینکهای خراب و علت عدم برقراری ارتباط سرویسها کنید. از اینرو، مهم است که این فرآیندها در کمترین زمان ممکن انجام شوند.
مدیریت بر مکانیزمهای ارتباطی سرویسها با هدف بهینه کردن عملکرد یک برنامه کاربردی، باعث میشود سرویسها بهطور یکپارچه با هم ارتباط برقرار کنند. برای برقراری ارتباط سرویسها با کانالهای خارجی، ضروری است یک دروازه API یا یک سرویس مدیریت پیام شبیه به کافکا پیادهسازی شود. این دروازههای پیام باید مسیریابی، محدود کردن نرخ و فیلتر درخواست را مدیریت کنند. همچنین، استقرار مکانیزمی در برنامه که بتواند دادههای مربوط به درخواستها را ذخیرهسازی کند و در صورت عدم موفقیت در پاسخگویی به درخواست دومرتبه فرآیند را تکرار کند، مهم است.
برقراری ارتباطات داخلی سرویسبهسرویس، پیگیری وضعیت سرویسهای توزیعشده و نحوه رسیدگی به درخواستها باید در طرحی که قرار است پروژه بر مبنای آن پیادهسازی شود، تعریف شود. ابزارهای منبعباز مختلفی مثل Jaeger و Zipkin میتوانند این فرآیند را مدیریت کنند. فناوری مشسرویس مانند ایستیو (Istio) نیز عملکرد قابل قبولی در این زمینه دارد که قابلیت ادغام با Jaeger و Zipkin را دارد. بهعنوان یک مکانیسم ارتباطی بینسرویسی، مشسرویس نقش بزرگی در کشف سرویس و نظارت بر ارتباطات سرویسبهسرویس ایفا میکند.
رسیدگی به خرابی سرویس
نکته مهمی که باید درباره خرابی سرویس به آن دقت کنید این است که خرابی در سطح یک سرویس، تنها مانع از کارکرد درست آن سرویس میشود و باعث نمیشود عملکرد برنامه متوقف شود. در اینجا، توسعهدهندگان از تکنیکی که «الگوی قطعکننده مدار» نام دارد، استفاده میکنند. قطعکننده مدار، ماژول نرمافزاری است که توسط توسعهدهندگان ایجاد میشود و شبیه مدارشکنهای الکتریکی سنتی است که بین ماژول درخواست خدمات و نقاط پایانی که سرویسها را دریافت میکنند قرار میگیرد. ماژول فوق از یک مکانیسم قطع استفاده میکند تا ارتباط هر ماژول با کانال ارتباطی که وضعیت ناپایداری دارد و باعث بروز خطا میشود را قطع کند. در این حالت، توسعهدهندگان زمان کافی برای آزمایش دوباره اتصال، شناسایی و رفع خرابی کانال ارتباطی بین مولفهها خواهند داشت.
معماری میکروسرویسها فعالسازی سرویسهای منفرد را امکانپذیر میکند و اجازه میدهد فرآیند بهروزرسانی سرویسها بدون اثرگذاری بر بخشهای مختلف یک برنامه انجام شود. البته این حرف به این معنا نیست که بهروزرسانیها بدون مشکل خواهند بود و در نتیجه هنوز هم انجام آزمایشهای فنی ضروری است. به همین دلیل، سرویسها باید بهگونهای پیکربندی شوند که در صورت خرابی، بهطور خودکار به حالتهای پایدار قبلی بازگردند. برای این منظور، هر سرویسی باید بهطور منظم سلامت خود را گزارش دهد، بنابراین به سراغ ابزارهایی بروید که امکان نظارت بر سلامت سرویسها و تسهیل مکانیسمهای خودتعمیری را ارائه میکنند.
پنج اصل طراحی میکروسرویسها
برخی توسعهدهندگان تصور میکنند که معماری میکروسرویس تنها گزینه قابل قبول در زمینه توسعه است، اما ایده بدی نیست که فرآیند توسعه را ابتدا با معماری یکپارچه آغاز کنید، زیرا همواره امکان مهاجرت به میکروسرویسها با اعمال تغییراتی در معماری یکپارچه وجود دارد. البته نباید فراموش کنیم که معماری میکروسرویس شامل جزئیات زیادی است و برای مهاجرت به آن باید برنامهریزی دقیقی داشته باشید. موفقیت در زمینه معماری میکروسرویسها به این مسئله بستگی دارد که چگونه سرویسها با برنامههای خارجی و سرویسهای دیگر ارتباط برقرار کنند. علاوه بر این، عملکرد، تحمل خطا، مشاهدهپذیری بهتر، برنامهنویسی چندزبانه، اجرای سادهتر عملیات و تجربه کاربری بهتر، مسائل کوچکی نیستند که بتوان بهسادگی از کنار آنها عبور کرد.
هنگامی که توسعهدهندهای تصمیم میگیرد از میکروسرویسها استفاده کند باید به این نکته دقت داشته باشد که منحصربهفردترین سرویسها را توسعه دهد تا هر سرویس بتواند بهترین عملکرد خود را ارائه دهد. برای این منظور باید به پنج اصل اساسی طراحی میکروسرویسها که هدف واحد، گسسته بودن، قابلیت نگهداری دادهها، قابلیت انتقال دادهها و زودگذر بودن است، دقت کنید.
هدف واحد
ما میتوانیم نقاط ورود به یک سرویس را هدف واحد در نظر بگیریم. بهعنوان مثال، فرض کنید یک شرکت بازرگانی فعال در صنعت خودروسازی به دنبال ساخت برنامهای است که معاملهگران احتمالی را با یکدیگر و خود سازمان مرتبط کند. اولین نقطه هدف این برنامه، خرید و فروش خودروها است.
دومین نقطه، پرداخت هزینه خرید خودرو است. در حالی که این دو میکروسرویس ممکن است همراه با یکدیگر استفاده شوند، اما سرویسهای ترکیبی نیستند. هر عنصر مسئولیت رسیدگی به وظیفه متفاوتی را دارد و باید بهتنهایی نوشته شود.
رویکرد گسسته
اصطلاح دیگری که باید در زمینه طراحی به آن دقت کنید، ماهیت گسستگی است. تمام منطق و دادههایی که یک میکروسرویس برای انجام کار خود به آن نیاز دارد، داخلی و متمایز از دادههای دیگر میکروسرویس است.
یک میکروسرویس پیکربندی خاص خود برای دستیابی به بهترین عملکرد دارد و این پیکربندی نباید با پیکربندی میکروسرویس دیگری تداخل داشته باشد. این اصل طراحی میکروسرویس بهویژه زمانی مهم است که توسعهدهندگان نیاز به افزایش یا کاهش مقیاس یک سرویس با هدف پاسخگویی به بارهای کاری دارند.
قابلیت نگهداری دادهها
یک میکروسرویس نهتنها باید توانایی نگهداری دادههای خود را داشته باشد، بلکه دادههای آن باید مستقل از دیگر میکروسرویسها باشد. در بیشتر موارد، توسعهدهندگان ترجیح میدهند هر میکروسرویس پایگاه داده خود را داشته باشد. با اینحال، برخی مواقع، شرایط ایجاب میکند برخی میکروسرویسها پایگاه داده خود را با یکدیگر بهاشتراک بگذارند. در چنین شرایطی، هر میکروسرویس جداول خود را در پایگاه داده خواهد داشت. بهطور معمول، توسعهدهندگان از رویکرد اشتراکگذاری پایگاه داده برای کاهش هزینهها استفاده میکنند. با این حال، این نگرش، ناقض فلسفه طراحی میکروسرویسها است.
توسعهدهندگان اغلب باید استقلال دادهها و افزونگی را در طراحیهای خود در نظر بگیرند. در حالی که توسعهدهندگان اغلب از این اصل پیروی میکنند که هر میکروسرویس دادههای خود را نگهداری کند، اما این مسئله باعث تکثیر دادهها در سطح برنامه میشود. با اینحال، تقریبا بیشتر آنها افزونگی دادهها را بهعنوان بخشی از الگوی طراحی میکروسرویس پذیرفتهاند.
قابلیت انتقال دادهها
میکروسرویسهای مبتنی بر ویژگی حملپذیری، فرآیند استقرار ماژولها روی سرورها را به سادهترین شکل فراهم میکنند. این مفهوم شبیه به یک ایمیج کانتینری یا الگوی طراحی فارغ از سرور است. در چنین شرایطی بر مبنای فرهنگ «تحویل و استقرار مستمر» (CI/CD) امکان نصب یک میکروسرویس روی هدفی معین وجود دارد. بهعنوان مثال، یک توسعهدهنده میتواند یک میکروسرویس قابل حمل را روی یک ارائهدهنده خدمات ابری مثل Google Cloud مستقر کند. با این حال، اگر شرایطی پیش بیاید که ضروری باشد میکروسرویس روی زیرساخت ارائهدهنده دیگری نصب شود، فرآیند انتقال میکروسرویس به فضای ابری دیگری مثل AWS بدون تلاش مضاعف وجود دارد.
زودگذر
یک میکروسرویس زودگذر به این معنا است که میتوان آن را در هر زمان حذف کرد و بلافاصله به آخرین وضعیت پایدار بازگشت. ماهیت زودگذر یک کانتینر نهتنها فرآیند مدیریت برنامه را هر زمان مشکلی در یک کانتنیر شناسایی شود ساده میکند، بلکه هر زمان کانتینری آفلاین شود، به توسعهدهندگان اجازه میدهد بهسرعت مسئله را شناسایی کرده و برطرف کنند. البته، در این زمینه باید به نحوه مدیریت ریسمانهای فعال (Active Threads) و اطمینان از عدم وجود وابستگیهای مبتنی بر ریسمان در کدها دقت کرد.
این پنج اصل طراحی میکروسرویس باید در قلب هر معماری مبتنی بر ریزسرویسها مورد توجه قرار گیرند. کافی است هنگام طراحی هر مولفه جزئیات را بهدقت زیر نظر بگیرید تا بتوانید معماری کارآمدی طراحی کنید تا برنامه کاربردی بهترین عملکرد خود را ارائه دهد.