جمعه , ۳۰ فروردین ۱۳۹۸
خرید فالوور اینستاگرام خرید لایک اینستاگرام

طراحی مایکروسرویس واکنشی – بخش اول؛ تکه سنگ بزرگ را خورد کنید!

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

  1. بخش اول – طراحی مایکروسرویس
  2. بخش دوم – سیستم‌های واکنشی
  3. بخش سوم – برنامه نویسی واکنشی
  4. بخش چهارم – مدل بازیگر

تکه سنگ بزرگ مشکی در فیلم ادیسه فضایی ۲۰۰۱ را یادتان است؟! در گذشته پروژه‌های بزرگ و سازمانی بصورت یکپارچه مانند یک قطعه سنگ بزرگ و سخت توسعه داده می‌شدند که تمام ماژول‌های آن در یک بسته قرار می‌گرفتند. با اضافه شدن امکانات مختلف به نرم‌افزار، این تکه سنگ بزرگ و بزرگ‌تر می‌شد. اما توسعه‌دهندگان نرم‌افزارهای یکپارچه به مرور زمان با مشکلات مختلفی روبرو می‌شوند:

  • با افزایش بیش از حد کد نرم‌افزار، توسعه آن سخت‌تر و زمان‌بر می‌شود.
  • نمی‌توان به راحتی یکی از بخش‌های نرم‌افزار را در دیگر پروژه‌ها استفاده کرد.
  • تغییر و ارتقاء پشته تکنولوژی استفاده شده بسیار سخت‌تر و زمان‌بر می‌شود.
  • یک خرابی در بخشی از سیستم می‌تواند کل سیستم را از کار بیاندازد.
  • برای مقیاس‌پذیری باید کل نرم‌افزار را در میزبانی دیگر راه‌اندازی کرد درصورتیکه شاید تنها تکثیر و راه‌اندازی یک بخش کوچک از کل نرم‌افزار مشکل را حل کند.
  • تغییرات کوچک نیاز به کامپایل و ساخت کل نرم‌افزار دارد که بسیار زمان‌بر است.
  • و …

برای حل مشکل بالا نیاز است که با استفاده از روش‌های مختلف مانند طراحی دامنه محور (ِDomain-Driven Design)، این سنگ بزرگ را به قطعات کوچکتر (سرویس) تبدیل کرد و هر کدام از این سرویس‌ها را بصورت جدا توسعه کرد.

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

ارتباط بین اجزاء مختلف سیستم و سرویس‌ها بر روی شبکه و بر اساس پروتکل های خاص انجام می‌شود. به چنین سیستمی، سیستم با معماری سرویس محور (Service-Oriented Architecture) گفته می‌شود. در این معماری، سرویس‌ها با استفاده از گذرگاه سرویس سازمانی (Enterprise Service Bus) با یکدیگر در ارتباط هستند. با استفاده از این گذرگاه، سرویس‌ها داده‌های مورد نیاز خود را با یکدیگر تبادل می‌کنند. و همچنین از این گذرگاه می‌توان به عنوان مدیریت همگام‌سازی تراکنش‌ها بین چندین سرویس، بررسی امنیت و یا یک دروازه برای تعامل کاربر و یا دیگر سرویس‌های خارجی با سیستم استفاده کرد.

با اینکه بسیاری از مشکلات نرم‌افزارهای یکپارچه حل شده بود اما همچنان معماری سرویس محور در برخی از زمینه‌ها با محدودیت‌هایی همراه بود. به عنوان مثال اگر گذرگاه ESB از دسترس خارج شود، کل سیستم از کار خواهد افتاد. سپس معماری مایکروسرویس معرفی شد تا به حل این محدودیت‌ها بپردازد. البته این بدان معنی نیست که معماری SOA قدیمی شده و دیگر مناسب نیست و همه باید از مایکروسرویس استفاده کنند! خیلی‌ها بر این باورند که مایکروسرویس، زیرمجوعه‌ای از معماری SOA است و بسیاری از سازمان‌های بزرگ همچنان از معماری SOA استفاده می‌کنند.

مایکروسرویس یک الگوی معماری نرم‌افزار است که در آن نرم‌افزار یکپارچه (تکه سنگ!) به اجزاء بسیار کوچک و مستقل تبدیل می‌شود که با یکدیگر در ارتباط هستند. همانطور که گفته شد مایکروسرویس زیرمجوعه‌ای از معماری SOA است و نمی‌توان این دو را در برابر یکدیگر قرار داد. با این حال در جدول زیر سعی شده است تا بخشی از تفاوت‌ها بیان شود.

معماری مایکروسرویس معماری سرویس محور
تمرکز بیشتر بر اصول مسئولیت واحد در هر سرویس و جداسازی (Decoupling) سرویس‌ها می‌توانند بزرگتر باشند و تمرکز بر روی استفاده مجدد از عملکردهای کسب‌وکار است
تمرکز بر افراد و ارتباط آن‌ها با یکدیگر و آزادی تصمیم‌گیری در هر سرویس استانداردها و قوانین یکسان برای سرویس‌ها و تیم‌های توسعه دهنده سرویس‌ها
سیستم تبادل پیام ساده استفاده از گذرگاه سرویس سازمانی
استفاده از پروتکل‌های سبک برای تبادل پیام (مانند REST یا gRPC بر روی HTTP 1.1/2) استفاده از پروتکل‌های تبادل پیام (مانند SOAP)
مقیاس‌پذیری بهتر و آسان‌تر  مقیاس‌پذیری محدود به دلیل وجود مؤلفه‌ی آسیب‌پذیر تکین (ESB)

در بسیاری از مقالات مقایسه آمده است که در مایکروسرویس از تکنولوژی‌های جدید مانند Docker و DevOps و حتی پایگاه‌داده‌های NoSQL استفاده می‌شود اما در معماری SOA از تکنولوژی‌های قدیمی‌تر استفاده می‌شود که این درست نیست. زمانی‌که معماری SOA معرفی شد هنوز آن تکنولوژی‌ها وجود نداشتند و یا هنوز فراگیر نشده بودند بنابراین بیشتر از تکنولوژی‌های فراگیر زمان خود استفاده می‌شده است. می‌توان یک نرم‌افزار با معماری SOA نوشت و از تکنولوژی‌های جدید نیز استفاده کرد. در حقیقت، نباید در همه جا طراحی و معماری را وابسطه به تکنولوژی دانست.

اصول طراحی سیستم‌های مایکروسرویس

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

هم‌بستگی بالا (High Cohesion)

میزان هم‌بستگی مشخص می‌کند که یک سرویس چه کاری می‌تواند انجام دهد. هم‌بستگی پایین زمانی رخ می‌دهد که تعداد زیادی از کارهای مختلف و متنوع در آن سرویس انجام شود که این طراحی نامناسب است. زمانی می‌گوییم که یک سیستم دارای هم‌بستگی بالا است که آن سرویس فقط و فقط یک کار مشخص را انجام دهد و تنها یک دلیل برای تغییر آن وجود داشته باشد که به آن اصل مسئولیت واحد (Single Responsibility Principle) نیز گفته می‌شود. بنابراین رعایت اصل مسئولیت واحد در مایکروسرویس باعث افزایش میزان هم‌بستگی می‌شود. این تعاریف نه تنها در معماری مایکروسرویس، بلکه در طراحی کلاس و ماژول در بحث شیء گرای نیز کاربرد دارد.

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

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

خودمختار (Autonomous)

برای اینکه یک مایکروسرویس خودمختار باشد و بتواند به طور کاملاً مستقل نسبت به دیگر سرویس‌ها قابل تغییر و استقرار باشد، باید میزان ارتباط و وابستگی آن به دیگر اجزاء کاهش یابد. ارتباط و وابستگی (Coupling) مشخص می‌کند که به چه اندازه دو سرویس به یکدیگر وابسته هستند. یکی از نشانه‌های وابستگی بالا آن است که در صورت ایجاد تغییر در یک مایکروسرویس، باید تغییری در مایکروسرویسی مرتبط با آن نیز ایجاد کنیم. از دیگر نشانه‌های آن، ارتباط بسیار زیاد و چَت مانند دو سرویس است.

ارتباط و وابستگی مایکروسرویس‌ها باید حداقل باشد و کمترین دانش را نسبت به یکدیگر داشته باشند و از طریق شبکه با یکی از دو روش همگام (Synchronous) و یا ناهمگان (Asynchronous) انجام شود.

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

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

دامنه محور (Domain-Driven)

هر مایکروسرویس باید یک عملکرد و دامنه کسب‌وکار را ارائه دهد. برای رسیدن به این هدف ابتدا باید دامنه‌های کسب‌وکار را به خوبی شناسایی کرد.

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

انعطاف‌پذیر (Resilience)

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

به عنوان مثال، طولانی شدن زمان پاسخ‌دهی به درخواست (مانند یک تراکنش) باعث می‌شود که سرویس طولانی مدت از دسترس خارج شود. برای جلوگیری از این مشکل باید فرض کرد که درخواست با شکست مواجه شده است و با استفاده از Timeout، انتظار سرویس را لغو کرد

دیده‌بانی (Observable)

باید بتوان اطلاعات کلی از عملکرد و سلامت سرویس‌ها و سیستم کلی را به راحتی بدست آورد. برای رسیدن به این هدف، از یک سرویس نظارت مرکزی بی‌درنگ (Real-Time) استفاده می‌شود که با همه سرویس‌ها در ارتباط است. این سرویس وظایف زیر را بر عهده دارد:

  • نظارت بر سخت‌افزار (میزان مصرف پردازنده، حافظه، دیسک، …).
  • معیارهای استفاده شده در سرویس‌ها (زمان پاسخ‌دهی، خطاها، …).
  • معیارهای مربوط به کسب‌وکار (تعداد سفارش‌ها، …).
  • جمع‌آوری و پردازش وقایع ثبت شده برای دست‌یابی به اطلاعات کلی‌تر.
  • ارسال اخطار به افراد مسئول در صورت وقوع خطا.

خودکارسازی (Automation)

به دلیل تعداد بالای مایکروسرویس‌ها، پیچیده بودن مدیریت، دشواری استقرار و ارتقای آن‌ها، باید از روش‌ها و ابزارهایی برای تست، بازخورد و استقرار آسان آن‌ها استفاده کرد. یکی از این روش‌ها یکپارچه‌سازی مداوم (Continuous Integration) و تداوم استقرار (Continuous Delivery) است که معمولاً از طریق یک سیستم کنترل منبع (Source Control System) پیاده‌سازی و استفاده می‌شوند. با استفاده از این ابزارها می‌توان نرم‌افزار و هر کدام از سرویس‌ها را بصورت خودکار بعد از ثبت هر تغییری در کد در سیستم کنترل منبع تست کرد و تحویل داد و در صورت وجود هرگونه مشکل در این مراحل، به افراد مسئول اطلاع داده می‌شود تا در سریع‌ترین زمان ممکن مشکلات را ریشه‌یابی و برطرف کنند.

نتیجه‌گیری

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

منابع:

  1. Microservices Architecture – Rag Dhiman
  2. BMC Blogs
 

درباره ی سینا نوریان

Avatar
کارشناسی ارشد نرم‌افزار از دانشگاه علم و صنعت ایران، برنامه‌نویس ارشد شرکت فناوران دانشگر. علاقه‌مند به سیستم‌های توزیع شده، معماری‌های مایکروسرویس و واکنشی، پردازش موازی و داده‌های جریانی. زبان‌های مورد علاقه: Scala, Go, Java

1
دیدگاه بگذارید

avatar
1 موضوع دیدگاه‌ها
0 موضوع پاسخ‌ها
0 دنبال‌کنندگان
 
بحث‌برنگیزترین دیدگاه
داغ‌ترین دیدگاه
1 نویسنده‌های دیدگاه
javad brhouzi آخرین نویسنده‌های دیدگاه
  مشترک شدن  
جدیدترین قدیمی‌ترین بیشترین امتیاز
اطلاع‌رسانی
javad brhouzi
Guest
javad brhouzi

خیلی خوب بود تبریک میگم هرچند فک میکنم به جای Observable از Monitoring استفاده میکردی بهتر بود