مرتضی دلیل
مرتضی دلیل
خواندن ۸ دقیقه·۳ سال پیش

آموزش میکروسرویس Microservice - آشنایی با مفهوم میکروسرویس (بخش اول)

بخش اول : آشنایی با مفهوم میکروسرویس (همین مقاله)
بخش دوم : ویژگی های اصلی یک میکروسرویس
بخش سوم : تحلیل یک پروژه کوچک بر اساس میکروسرویس ها
بخش چهارم : شروع پیاده سازی یک پروژه فروشگاهی
پیشنیاز 1 بخش پنجم : آموزش Node و Typescript برای تولید api
پیشنیاز 2 بخش پنجم : آموزش داکر و مفاهیم اولیه
بخش پنجم : پیاده سازی یک میکروسرویس برای نمایش کالاها
پیشنیاز 1 بخش ششم : آشنایی با Asp.net core 6
بخش ششم : پیاده سازی یک میکروسرویس برای کار با سبد خرید
بخش هفتم : پیاده سازی یک میکروسرویس برای محاسبه قیمت و تخفیفات
بخش هشتم: پیاده سازی یک میکروسرویس برای ثبت سفا رش


برای دیدن ویدیوهای من در مورد برنامه نویسی عضو این کانال شوید :
https://t.me/mediapub_channel

در این مقالات با یک پروژه عملی پر از جزئیات روبرو هستید.(همین اول تکلیفمون مشخص شد!)

پیش از این مجموعه مقالاتی را در مورد Clean Architecture تهیه و در اختیار شما قرار داده بودم که بازخورد خوبی داشت. این مقالات را از طریق این لینک میتوانید مشاهده کنید.

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

این مقالات مناسب افرادیست که با برنامه نویسی آشنایی دارند و چندین پروژه را انجام داده اند.

اینکه به چه زبان برنامه نویسی مسلط هستید اهمیتی ندارد.

برای نوشتن مطالب از ویدیوهای مربوط به میکروسرویس در pluralsight و udemy و کتاب microservice in action و نت های خودم استفاده کرده ام.

حین نوشتن مطالب تمام سعی من این بوده که وقت شما را تلف نکنم. میکروسرویس هایی که به عنوان مثال طراحی کرده ام با زبان های مختلف برنامه نویسی نوشته ام. فرض من این است شمایی که سراغ میکروسرویس آمده اید حداقل به یک زبان تسلط دارید و دیدن کدهای زبان های دیگر برای شما آزاردهنده نیست. اینکه چطور فریم ورک ها و کتابخانه ها و زبان های مختلف برنامه نویسی در کنار هم یک هدف را برآورده میکنند بسیار جذاب است.

امیدوارم این مطالب مفید باشد.


میکروسرویس چیست؟

یک شیوه معماری است. سرویس مستقل و محدود شده و «به تنهایی قابل انتشار» که قابلیت تعامل با سرویس های دیگر را دارند و در مجموع یک اپلیکیشن را می سازند.

اگر بخواهیم خودمانی تر میکروسرویس ها را معنی کنیم، یعنی سرویسی که آنقدر متمرکز روی یک موضوع فعالیت می‌کند(مستقل) که حجم کد کم و مسئولیت کمتری دارد(محدود شده). این سرویس api هایی را در معرض «درخواست های بیرونی» قرار می‌دهد که فقط در حوزه فعالیتش باشند(مستقل). «درخواست های بیرونی» هم شامل ریکوئست های کاربر هستند و هم شامل درخواست های دیگر سرویس ها (یا میکروسرویس ها).

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

میکروسرویس ها با هم یک «سیستم» را تشکیل میدهند و به روزرسانی هر کدام مستقل از بقیه سرویس هاست. پس «به تنهایی قابل انتشار» هستند.

چرا به میکروسرویس نیاز داریم؟

اپلیکیشن های قدیمی معمولا یکپارچه یا مونولیت (monolith) بودند. همه کدها در یک مکان قرار داشت و همه توسعه دهنده ها باید روی یک ریپازیتوری کار میکردند. معمولا اجرای یک کدِ واحد، روی یک سرور واحد و دسترسی بیرونی به این اجرا، تمام چیزی بود که باید اتفاق می افتاد؛ دیتابیس هم یکی و همان بغل بود! از فریم ورک و زبان برنامه نویسی واحدی هم برای کل پروژه استفاده می‌شد. نکته مثبت این روش، ساده بودن توسعه و دسترسی سریع تر به کدها بود. برای انتشار هم یک Build ساده و publish کافی بود و تمام.

اما مشکل کجاست؟

بزرگترین مشکل، تغییر Scale اپلیکیشن بود. این روش برای زمانی که یک برنامه نویس داریم یا تیم کوچکی مسئول پروژه است و قرار است در چند ماه توسعه به پایان برسد و تعداد کاربران محدودی استفاده کننده، مناسب است. اما وقتی پروژه بزرگ شود و مثلا سی یا چهل توسعه دهنده داشته باشیم، شکل مساله تغییر میکند. ممکن است این تیم سال ها روی اپلیکیشن کار کنند، اپلیکیشن درگیر کاربران زیادی باشد و دیتا روز به روز افزایش پیدا کند. مشکل اپ های مونولیت همین بود که افزایش حجم کد و دیتا باعث می‌شد نگهداری بسیار سخت شود. به همین دلیل، راه حل ماژولار کردن پیش از این، تا حدی کمک میکرد اما باز هم در هم تنیدگی ماژول ها و یکپارچه بودن کد مساله ساز میشد.

در اپلیکیشن های مونولیت تغییر یک خط کد نیازمند Build و Publish کل اپلیکیشن بود. این کار ریسک دارد و باید حتما در مواقعی که بار کاربر روی سیستم کم است انجام شود. این روش در سیستم های جدید به دلیل High Avaibility بودن یا همیشه در دسترس بودن، مشکل زا خواهد بود. افزایش کاربر یا افزایش حجم دیتا در اپلیکیشن های monolith باعث سختی کار میشد. معمولا راه حل توسعه Vertical بود. یعنی افزایش هزینه با خرید سرور قدرتمند یا سخت افزار جدید با قدرت پردازش بالا.

پس مشکل اینجاست که اپلیکیشن مونولیت خودش را با تکنولوژی و روش های کهنه گره زده و توسعه و نگهداری آن هزینه زاست، چه برسد که بخواهید فریم ورک یا ماژول های اصلی را تغییر دهید. تغییر یک بخش کوچک هزینه زمانی و ریسک بزرگ دارد. آپدیت ها در فاصله زمانی طولانی تر با درجه ریسک بالاتر و در زمان خلوت بودن سرور قابل انجام است. (کم کردن ریسک نیازمند تست های بیشتر و عمیق تر، و اتلاف وقت بیشتر است). در مجموع agility یا چابکی سیستم با روش قدیمی کاهش می یابد. اضافه کردن ابزار جدید یا سرویس های جدید هزینه زاست.

من تا الان قواعد میکروسرویس را رعایت کرده ام؟

ممکن است ادعا کنید که تا الان سعی کرده اید بخشی از این قواعد را رعایت کنید تا اپلیکیشنتان خیلی هم مونولیت نباشد. مثلا سرویس های جدا از هم نوشته اید که همدیگر را صدا میزنند. شاید چیزی شبیه به تصویر زیر پیاده سازی کرده اید.

تصویر از دوره آموزشی میکروسرویس در pluralsight
تصویر از دوره آموزشی میکروسرویس در pluralsight


شما یک سیستم distributed monolith طراحی کرده اید که وابستگی همه به یک دیتابیس کار را برای توسعه و نگهداری و پابلیش سخت میکند. هر تغییر در هر سرویس یا دیتابیس مستلزم پابلیش همه سرویس ها در انتشار نهایی است. در میکروسرویس ها یکی از اصول جدا بودن Data Store ها است.

میکروسرویس ها چطور به ما کمک می کنند؟

  • اپلیکیشن به سرویس های کوچکتر تقسیم می شود : هر سرویس کوچک می تواند توسط تیم جدا توسعه یابد. طبیعتا درک کار این سرویسها راحت تر خواهد بود و آنقدر سایز میکروسرویس ها کوچک میشود که قابل بازنویسی با یک روش جدید، فریم ورک جدید و حتا زبان برنامه نویسی جدید هستند. میکروسرویس تک وظیفه است و وظیفه اش معطوف به قابلیتی است که از آن انتظار داریم.
  • آزادی در انتخاب تکنولوژی در هر ماژول : بدون اینکه نیاز به به روزرسانی کل سیستم داشته باشیم میتوانیم یک ماژول را بازنویسی کنیم. انتخاب و تغییر ابزار یا به تعبیری انعطاف پذیری در انتخاب ابزار مناسب، سرویس های دیگر را تحت تاثیر قرار نمیدهد. مثلا یک سرویس از دیتابیس Relational استفاده میکند و سرویس دیگر از یک دیتابیس No-Relational. یک سرویس بر اساس Functional Programming توسعه می یابد و یکی دیگر OOP است. یک سرویس با پایتون نوشته میشود و سرویس دیگر با دات نت.
    این آزادی در انتخاب تکنولوژی، سبک یا استاندارد کد نویسی هر میکروسرویس را محدود به خودش میکند. اینکه قواعد نامگذاری یا استایل نوشتن و استفاده از کتابخانه ها به چه روشی باشد محدود به همان میکروسرویس است و لازم نیست شما یک الگوی کلی را برای همه میکرسرویس ها رعایت کنید. پس واگذاری هر میکروسرویس به یک تیم برنامه نویسی جدا، وقت و انرژی کمتری از شما و همه خواهد گرفت.
  • توسعه مستقل هر میکروسرویس : ریسک کمتری در آپدیت ها وجود دارد چون کل سیستم آپدیت نمیشود. با اینکار downtime سیستم به صفر میرسد چون هنگام آپدیت بقیه سیستم دست نخورده باقی میماند و به کار خود ادامه میدهد. این مزیت باعث میشود تیم توسعه بتواند دفعات آپدیت خود را به دلیل توسعه سریع افزایش دهد (به جای اینکه برای موعد مشخصی برنامه ریزی آپدیت انجام دهد)
  • کنترل بیشتر روی Scalibility : میتوان هر سرویس را به طور مستقل از دید پرفورمنس و بهینه سازی و شکل دسترسی تغییر داد.
  • افزایش Agilibility : سرعت رفع باگ و توسعه و اضافه کردن متدهای جدید با کمترین سایدافکت بیشتر از حالت مونولیت است.


چالش های میکروسرویس ها چیست؟

  • آشنایی توسعه دهنده از شکل تعامل میکروسرویس ها : استفاده از میکروسرویسهای دیگر به عنوان یک سرویس مستقل برای دسترسی به اطلاعات شاید وقت گیر و پر خطا باشد. توسعه دهنده باید روش و دستورالعمل مشخصی برای استفاده از دیگر سرویس ها داشته باشد. ممکن است توسعه دهنده برای تست سرویس خود در بستر یک اپلیکیشن (پر از میکروسرویس های دیگر) با مشکل مواجه شود. اگر ده ها میکروسرویس داشته باشیم ارتباط این سرویس ها به مرور زمان پیچیده میشود و فهم کارکرد کل سیستم برای کسی که با روند آشنایی ندارد و تازه وارد تیم شده سخت خواهد بود. این نادانی باعث ایجاد مشکلات پرفورمنسی میشود. یعنی ارتباط بین میکروسرویس ها مشکل ساز و غیرکارآمد خواهد شد.
  • انتشار خودکار یک تیغ دو لبه : اینکه میکروسرویس باعث میشود شما به سمت طراحی یک انتشار خودکار پیش بروید یک مزیت است اما گاهی این تکرار انتشار و fixed bug ها ممکن است باعث بحران شود. تنها علت هم انتشار های بیشتر حین توسعه است که احتمال خطا را بیشتر میکند.
  • مشکل بررسی لاگ : اینکه هر میکروسرویس لاگ مخصوص به خودش را دارد و باید چاره ای برای یکپارچه سازی لاگ ها اندیشید یک چالش است. حل نکردن این چالش باعث میشود پیدا کردن منبع مشکل بیشتر از رفع مشکل وقت توسعه دهنده را بگیرد.


ویژگی های اصلی یک میکروسرویس

با توضیحاتی که به شکل توصیفی پیش از این مطالعه کردید میتوان نتیجه گرفت که اصول طراحی یک معماری میکروسرویس بر اساس تقسیم بندی زیر قابل بررسی است :

  1. میکروسرویس تک وظیفه است. (Single Responsibility)
  2. میکروسرویس به طور مستقل قابل انتشار است.
  3. میکروسرویس میتواند یک یا چند پراسس داشته باشد. (مثلا یک بک گراند سرویس برای انجام یک کار دیگر در پشت صحنه)
  4. میکروسرویس منبع مستقل ذخیره سازی داده دارد.
  5. نگهداری میکرسرویس با تیم کوچکی قابل انجام است.
  6. میکروسرویس قابل تعویض یا جایگزینی است.


هر کدام از این اصول را در بخش بعد به تفصیل و با مثال توضیح خواهم داد. اگر مشکل یا سوالی بود در بخش نظرات مطرح کنید تا نسبت به شکل ارائه مطالب مطلع بشم و در مقالات بعدی اصلاح کنم.

میکروسرویسmicroserviceبرنامه نویسی
برنامه نویس و علاقمند به برنامه نویسی، سینما، فلسفه و هر چیزی که هیجان انگیز باشد. در ویرگول از روزمرگیهای مرتبط با علاقمندیهام خواهم نوشت. در توئیتر و جاهای دیگر @mortezadalil هستم.
شاید از این پست‌ها خوشتان بیاید