امروزه با نیاز رو به رشدی که به اپلیکیشنهای بزرگ اینترپرایز به وجود آمده است، مفهومی تحت عنوان میکروسرویس هم در صنعت توسعهٔ نرمافزار رواج یافته است چرا که دولوپرها برای توسعهٔ سیستمهای بزرگ تجاری چارهای جز بهکارگیری از معماری میکروسرویس ندارند. در ظاهر مفهوم میکروسرویس کمی پیچیده به نظر میرسد اما در واقعیت هرگز اینگونه نیست و در این پست قصد داریم چیستی، چرایی و همچنین مزایا و معایب بهکارگیری از میکروسرویسها را مورد بررسی قرار دهیم.
معماری Monolithic چیست؟
برای درک ماهیت میکروسرویسها، ابتدا باید ببینیم که معماری Monolithic چگونه کار میکند. به طور کلی، در این نوع معماری ما سه لایه داریم تحت عناوین:
- Model (منطق اپلیکیشن)
- View (خروجی اپلیکیشن)
- Controller (رابط مابین خروجی و منطق اپلیکیشن)
برای روشنتر شدن این مسئله، مثالی میزنیم. در حال حاضر که مشغول مطالعهٔ این مقاله هستید، به محض اینکه وارد این صفحه شدید، یک ریکوئست (درخواست) برای سرور سکان آکادمی ارسال گردیده است که لایهٔ مرتبط با Controller این درخواست را گرفته و برای لایهٔ Model ارسال میکند و این لایه هم با دیتابیس ارتباط برقرار ساخته و دیتای مرتبط با این مقاله را از دیتابیس فراخوانی کرده و در صورت نیاز یکسری کارها برای تر و تمیز کردن دادهها انجام داده و در نهایت مجدد دیتا در اختیار Controller قرار میدهد و این لایه هم دیتای موجود را در اختیار View میگذارد و این لایه هم خروجی این صفحه از وبلاگ سکان آکادمی را داخل مرورگر شما نشان میدهد.
مشکلات مرتبط با معماری Monolithic
این نوع معماری که تحت عنوان معماری MVC هم شناخته میشود دارای یکسری نواقصی است. به عبارت دیگر، تمامی لایهها (مدل، ویو و کنترلر) زیر پرچم یک پلتفرم واحد مدیریت میشوند و ارتباط بسیار تنگاتنگی با یکدیگر دارند و مثلاً به سادگی نمیتوان Model یک اپلیکیشنی که تحت معماری MVC نوشته شده را برداشته و در پروژهٔ دیگری استفاده کرد.
همانطور که در تصویر فوق مشخص است، در معماری Monolithic یک هستهٔ مرکزی داریم که کاربران و حتی دیگر سرویسها از طُرق مختلف میتوانند با آن ارتباط برقرار سازند و میبینیم گرچه خودِ این هستهٔ مرکزی ماژولار (بخشبندی) است، اما همگی تحت یک پلتفرم واحد کنار یکدیگر قرار گرفتهاند و امکان مجزاسازی این ماژولها وجود ندارد و یا اگر هم چنین امکانی وجود داشته باشد، بسیار دشوار خواهد بود (برای آشنایی بیشتر با این معماری میتوانید به آموزش آشنایی با عملکرد مدل، ویو و کنترلر در وب اپلیکیشنی که بر پایهٔ الگوی معماری MVC نوشته شده باشد مراجعه نمایید.)
اگرچه که در معماری MVC کدها ماژولار هستند و نسبت به گذشته که تمامی فایلها در یک پوشه گذاشته میشدند و اصلاً مفهومی تحت عنوان ماژول در کار نبود شرایط به مراتب بهتر است، اما همانطور که گفته شد، هر ماژول برای کارکرد صحیح و اصولی خود نیاز به سایر ماژولها دارد. به طور کلی، مشکلات مرتبط با معماری Monolithic را میتوان به دستههای زیر تقسیمبندی کرد:
- از آنجا که یک سورسکد اصلی بیشتر وجود ندارد، تکتک اعضای تیم، از دولوپر فرانتاند گرفته تا برنامهنویسهای سمت سرور و غیره، باید روی یک سورسکد کار کنند و به طور مثال اگر کسی بخواهد صرفاً روی بخش مدیریت کاربران کار کند، باید کل پروژه را دریافت کرده، یک هاست لوکال پیکرهبندی کرده و شروع به کار روی پروژه کند.
- یک تغییر کوچک در یکی از ماژولها، ممکن است عملکرد دیگر ماژولها را تحتتأثیر خود قرار دهد.
- درست است که در این نوع معماری مفهومی داریم تحت عنوان MVC، اما در طول زمان این سه لایه آنقدر با یکدیگر عجین خواهند شد که به سختی میتوان مرز مشخصی مابین آنها ایجاد کرد.
- کامپوننتها را به سادگی نمیتوان با یک معماری جدیدتر و بهینهتر جایگزین کرد چرا که کل معماری نرمافزار باید دستخوش تغییر گردد.
- تنوع تکنولوژی منجمله زبانهای برنامهنویسی، دیتابیسهای مختلف، لایبرریها و فریمورکهای مختلف وجود نخواهد داشت و اگر هم اینگونه باشد، ارتباط برقرار کردن مابین آنها بسیار دشوار خواهد بود.
- و یک باگ در یکی از ماژولها، به احتمال زیاد کل پروژه را تحتالشعاع خود قرار خواهد داد.
اینجا است که پای میکروسرویسها به میان میآید و مزایایش منجر بدین گشته تا کمپانیهای بزرگی همچون آمازون یا نتفلیکس به استفاده از میکروسرویسها ترغیب شوند.
معماری Microservice چیست؟
میکروسرویس روشی به منظور تقسیمبندی کردن یک اپلیکیشن (نرمافزار) به بخشها یا سرویسهای کوچک، سبُک، مستقل از یکدیگر و قابلمدیریت است. به عبارت دیگر، میکروسرویس یک معماری توسعهٔ نرمافزار به اصطلاح Distributed است.
همانطور که در تصویر فوق مشاهده میشود، این نوع سرویسها صرفاً به منظور هندل کردن یک تَسک خاص طراحی میشوند. به طور مثال، یک سرویس صرفاً وظیفهٔ مدیریت کاربران را دارا است و سرویس دیگر فقط و فقط برای بخش جستجوی سایت کاربرد دارد و با توجه به اینکه میکروسرویسها مجزا و مستقل از یکدیگر هستند، به راحتی قادر خواهیم بود تا آنها را با زبانهای برنامهنویسی مختلفی نوشته و برای ذخیرهسازی دادههای مرتبط با آنها نیز از سیستمهای مدیریت دیتابیس مختلفی استفاده کنیم (به عبارت دیگر، جاهایی که نیاز به ذخیرهسازی سنتی دادهها داریم میتوانیم از MySQL استفاده کنیم و جاهایی دیگر هم به خاطر ساختار غیرقابل پیشبینی دیتای خود میتوانیم به استفاده از دیتابیسهای به اصطلاح NoSQL بپردازیم.)
حال ممکن است این پرسش مطرح شود که سرویسهای مختلف یک اپلیکیشن با معماری میکروسرویس چگونه با یکدیگر ارتباط برقرار میکنند؟ در پاسخ به این سؤال باید گفت، همانطور که در تصویر فوق مشخص است، با استفاده از ریکوئستهایی از جنس HTTP و یکسری API به اصطلاح RESTful این ارتباط برقرار خواهد شد (برای آشنایی بیشتر با این اصطلاح، به آموزش API چیست؟ مراجعه نمایید.)
آشنایی با معماری Service Oriented Architecture
اینجا سؤال دیگری به ذهن میرسد و آن هم اینکه با این تفاسیر تفاوت چندانی مابین Service Oriented Architecture یا به اختصار SOA با Microservice وجود ندارد که در پاسخ به این سؤال هم میتوان گفت که Microservice نوعی SOA (معماری مبتنی بر سرویس) است که طی دههای گذشته خیلی مطرح بوده است اما در عین حال میکروسرویس نسبت به معماری مبتنی بر سرویس انعطافپذیرتر است چرا که به سادگی میتوان یک سرویس یا ماژول را از پروژهای برداشت و بدون پیکرهبندی خاصی آن را در پروژهٔ دیگری استفاده کرد اما این در حالی است که معماری SOA داخل یک معماری اصطلاحاً Monolithic پیادهسازی میشود.
به عبارت دیگر، در معماری SOA ما کامپوننتها یا ماژولهایی داریم که سرویسهایی را در اختیار دیگر کامپوننتهای قرار میدهند و این در حالی است که این کامپوننتها میتوانند منحصر به یک اپلیکیشن خاص باشند اما در مقابل در معماری یک Microservice این کامپوننتها به عنوان سرویسهای کاملاً مستقلی هستند که به صورت تکی هم میتوان آنها را دیپلوی کرد. نکتهٔ دیگری که در ارتباط با تفاوتهای این دو معماری نرمافزار باید مد نظر داشت، سایز ماژولها است. به عبارت دیگر، میکروسرویسها به مراتب کوچکترند و همین مسئله مدیریت آنها را به مراتب سادهتر میسازد.
آشنایی با تفاوتهای معماریهای Microservice ،Monolithic و SOA
برای درک بهتر تفاوتهای مابین معماریهای Microservice ،Monolithic و SOA میتوان اولین تصویری که در این مقاله استفاده شده را مد نظر قرار داد. در واقع از چپ به راست، معماریهای SOA ،Monolithic و Microservice در قالب خوراکی به تصویر کشیده شدهاند.
در تصویر سمت چپ میبینیم که معماری Monolithic به گونهای است که ارتباط تنگاتنگی مابین ماژولهای مختلف اپلیکیشن وجود دارد که اصطلاحاً گفته میشود Tightly Coupled است و در صورتی که بخواهیم تغییری در یکی از بخشها دهیم با مشکل مواجه خواهیم شد و همین مسئله Continous Deployment یا به اختصار CD را دشوار میسازد. در تصویر وسط که نشانگر معماری SOA است، میبینیم که اوضاع نسبت به معماری Monolithic به مراتب بهتر بوده به طوری میتوانیم اپلیکیشن را به بخشهای مجزا از یکدیگر تقسیمبندی کنیم اما در عین حال، هر بخش زیر چتر پلتفرم اصلی قرار دارد و در تصویر سمت راست هم که معماری Microservice در آن به تصویر کشیده شده است، بر خلاف دو معماری دیگر میبینیم که هر ماژول کاملاً مستقل از دیگر ماژولها است که اصطلاحاً گفته میشود Loosely Coupled است و همچون یک پیراشکی، میتوان آن را به تنهایی میل کرد!
مزایای استفاده از میکروسرویسها
امروزه ماژولار بودن به یک مزیت رقابتی در هر صنعتی مبدل شدهاند؛ از مبلمان IKEA گرفته تا گوشیهای موبایل ماژولار و حتی اسباببازیهای LEGO و این در حالی است که ایدهٔ پشت میکروسرویسها این است تا این امکان به دولوپرها داده شود تا اپلیکیشنهای خود را بر مبنای اجزا یا سرویسهایی که مستقل از یکدیگر هستند و به سادگی قابلتغییر، حذف و بهروزرسانی میباشند توسعه دهند بدون اینکه کل اپلیکیشن تحتالشعاع قرار گیرد. روی هم رفته، مهمترین مزایای استفاده از معماری میکروسرویس عبارتند از:
- بر خلاف معماری مونولیتیک، در یک اپلیکیشنی که در آن از معماری میکروسرویس استفاده شده باشد سرویسها هرگز بر اساس معماری MVC تقسیمبندی نمیشوند بلکه بر اساس کاری که انجام میدهند به بخشهای مختلف تقسیم میشوند. به عبارت دیگر، یک سرویس همچون آپلود فایل شامل بخشهایی همچون رابط کاربری، مدلهای مرتبط با دیتابیس، کنترلر، سیستم لاگینگ و ... خواهد بود (در چنین شرایطی، فرض کنیم دولوپر سرویسی تحت عنوان File Uploader میسازد و از آن پس به سادگی قادر خواهد بود سرویس مد نظر را در دیگر پروژهها که کاربرد یکسانی دارند نیز استفاده کند.)
- یکی دیگر از مزیتهای میکروسرویسها این است که ما مجبور به استفاده از صرفاً یک زبان برنامهنویسی یا فناوری در کل پروژه نمیشویم. در واقع، با توجه به اینکه امروزه برخی زبانهای برنامهنویسی برای حوزههای خاصی تخصصیتر هستند و استفاده از زبانی که اختصاصاً برای کار خاصی طراحی شده پرفورمنس اپلیکیشن ما را بالاتر میبرد، با استفاده از میکروسرویسها قادر خواهیم بود تا بسته به نوع سرویس مد نظر خود از چندین زبان برنامهنویسی و فناوری مختلف استفاده کرده و پرفورمنس را به حد اعلای خود برسانیم.
- علاوه بر موارد فوق، میکروسرویسها اصطلاحاً Scalable (قابلتوسعه) هستند. ماهیت مستقل ماژولهای مختلف یک میکروسرویس این امکان را برایمان فراهم میآورند تا با استفاده از زبانی خاص، دیتابیسی خاص و همچنین سروری خاص به توسعهٔ اپلکیکشن مد نظر خود بپردازیم و در صورت نیاز صرفاً منابع همان پلتفرم را ارتقاء دهیم.
معایب استفاده از میکروسرویسها
تا اینجای بحث از خوبیها میکروسرویسها گفتیم اما باید توجه داشته باشیم که این نوع معماری توسعهٔ اپلیکیشن نقاط ضعف خاص خود را هم دارا است که برخی از مهمترین آنها عبارتند از:
- از آنجا که هر سرویس مسئول انجام تَسک خاصی است، در اپلیکیشنها بسیار بزرگ تعداد سرویسهای بیشماری خواهیم داشت و از همین روی برقراری ارتباط مابین این سرویسها و از همه مهمتر مانیتور کردن آنها کاری بس دشوار خواهد بود (برخی دادهها حاکی از آنند که سرویسی همچون نتفلیکسن صدها سرویس مختلف دارد.)
- با توجه به اینکه سرویسها برای برطرف کردن نیازهای خود دیگر سرویسها را کال (فراخوانی) میکنند، رصد کردن آنها و بالتبع فرایند دیباگینگ بسیار دشوار خواهد شد.
- هر سرویس لاگگیری اختصاصی خود را دارا است و از همین روی هیچ سیستم مانیتورینگ مرکزی برای بررسی لاگها وجود ندارد و در چنین شرایطی نیاز به یک سیستم مدیریت لاگ مرکزی وجود خواهد داشت.
- با توجه به اینکه ارتباط سرویسها با یکدیگر از طریق API است، تعداد رکوئستها نسبت به یک معماری مونولیتیک به مراتب بیشتر خواهد بود.
- دیپلوی کردن اپلیکیشنهایی که با استفاده از معماری میکروسرویس طراحی شدهاند به صورت دستی مشکل است و در چنین شرایطی نیاز به ابزارهای اتوماسیون پیشرفته خواهد بود.
- ورژنبندی میکروسرویسها باید به صورت مجزا از یکدیگر صورت گیرد و اینجا است که نیاز داریم تا مشخص کنیم به طور مثال کدام ورژن سرویس A با کدام ورژن سرویس Z باید دیپلوی شود.
- مستنداتسازی چنین اپلیکیشنهایی مشکلتر است چرا که با توجه به ماهیت مستقل هر ماژول، سرویسها باید به صورت کامل مستندسازی شوند.
- با توجه به اینکه ممکن است از چندین زبان برنامهنویسی و تکنولوژی مختلف در چنین اپلیکیشنهایی استفاده شود، هزینهٔ نگهداری چنین سیستمها گاهی اوقات زیاد میشود به طوری که مثلاً نیاز به استخدام دولوپر زبانهای مختلف خواهیم داشت.
- امروزه اکثر اپلیکیشنها نیاز دارند تا در آنِ واحد چندین رکورد را در دیتابیس حذف یا بهروزرسانی کنند. در چنین مواقعی با توجه به اینکه در معماری مونولیتیک صرفاً یک دیتابیس وجود دارد، اینکار به سادگی صورت خواهد گرفت اما در میکروسرویسها چنین حذف یا بهروزرسانیهایی چالشی خواهند شد چرا که ممکن است رکوردی در دیتابیس یکی از سرویسها در یک سرور خاص به همراه رکورد دیگری در سرویس دیگری روی سرور دیگری بخواهند با یکدیگر سینک شوند.
چه زمانی به میکروسرویس مهاجرت کنیم؟
آنچه در ادامه خواهیم آورد، شرایطی است که اگر در مورد اپلیکیشن شما صدق میکند، زمان آن فرا رسیده که میکروسرویس هم جزو یکی از گزینههای پیش روی شما باشد:
- چنانچه سورسکد پروژهٔ شما آنقدر حجیم شده است که توسعهٔ آن به صورت لوکال، مثلاً لود کردن کل پروژه داخل یک IDE، کار دشواری شده است و نیاز به توضیح نیست که فرایند بیلد کردن برخی از پروژههای بسیار بزرگ که به صورت مونولیتیک نوشته شدهاند گاهی دهها دقیقه به طول میانجامد.
- صرفاً برخی بخشهای اپلیکیشن نیاز به توسعه دارند و این در حالی است که در معماری مونولیتیک شما باید به یک باره کل منابع سیستمی خود را ارتقاء دهید و این در صورتی است که ممکن است اصلاً نیاز به ارتقاء به این شکل نباشد.
- چنانچه دولوپرها در کنار یکدیگر نیستند و نمیتوانند به صورت مستقل از یکدیگر روی پروژه کار کنند.
جمعبندی
مبحث معماری میکروسرویس بسیار گسترده است و زمانی که بخواهیم وارد این حوزه شویم، نیاز است تا با مفاهیمی همچون Continuous Integration ،Continuous Deploymnet ،Container و همچنین ابزارهای دیپلوی خودکار نیز آشنا شویم اما آشنایی در همین حدی که در این پست صورت گرفت، برای هر دولوپری فارغ از اینکه بخواهد وارد این حوزه شود یا خیر، ضروری است (چنانچه علاقمند به مباحث مرتبط با میکروسرویسها هستید، میتوانید به پادکست مصاحبه با علی مقدم: رهبر فنی شرکت Cisco در رادیو فولاستک مراجعه نمایید.)
حال نوبت به نظرات شما میرسد. آیا تجربهٔ کار با معماری میکروسرویس را داشتهاید و به نظر شما مزایا و معیاب این نوع معماری چیست؟ نظرات، دیدگاهها و تجربیات خود را با سایر کاربران سکان آکادمی به اشتراک بگذارید.