این پست با همکاری جناب آقای مهندس رضا قاضینور تهیه شده است.
نیازمندیهای کسبوکار بر تکامل فناوریهای کامپیوتری عمیقا اثر گذار بوده است. بطور سنتی، نرمافزارها بصورت منولتیک توسعه داده میشدند. یعنی تمامی مولفه نرمافزار در یک ماشین قرار داشت و بصورت عمومی توسط یک نفر اجرا میشد. تمامی مولفهها بخشی از یک کل واحد بودند. بطور مثال فروشگاه برخط به شکل زیر در منولیت قابل تصور است.
از آنجایی که تمامی مولفهها قسمتی از یک کل واحد بودند، همه چیز در قالب یک واحد توسعه داده، پیادهسازی و مقیاس میشد. از یک تکنولوژی استک برای نوشتن کل برنامه استفاده میشد. تیمها باید مراقب میبودند که بر کار یکدیگر اثر نمیگذاشتند. از آنجایی که نرمافزار در قالب یک فرآورده بود، به ازای هر بار به روزرسانی باید کل نرمافزار را redeployکرد.
با بزرگتر شدن نرمافزار و افزایش پیچیدگی، معماری منولتیک چالشهای فراوانی را برای توسعه نرمافزار ایجاد میکرد. از جمله این چالشهای میتوان به دشواری هماهنگی بین تیمها، افزایش درهمتنیدگی (tangling) اجزا و مولفههای نرمافزار، عدم امکان مقیاسپذیری یک بخش یا مولفه به خصوص از نرمافزار (نرمافزار بصورت یک کل قابل مقیاس کردن بود)، بالاتر بودن هزینههای زیرساخت و انعطافپذیری پایینتر، طولانیتر بودن فرایند انتشار (به ازای هر تغییر، کل نرمافزار باید تست میشد، build و deploy باید بر روی کل نرمافزار انجام میشد و وجود باگ در هر ماژول بر روی کل نرمافزار اثر میگذاشت) و چالشهای مرتبط با ورژنهای مختلف میتوان اشاره کرد.
رشد فناوریهای شبکه و مفهوم اشتراک منابع کامپیوتری (از نظر سختافزاری و نرمافزاری)بین کاربران مختلف روی یک شبکه، سبب تغییر مفاهیم توسعه نرمافزار شد. این موضوع به جدا کردن نرمافزار به طبقههای مشخص کلاینت و سرور شد. کلاینت شامل ماشین فیزیکی بود که قسمت مربوط به کلاینت یا واسط مربوط به آن را اجرا میکرد. سرور شامل ماشین فیزیکی بود که هسته نرمافزار و اجز مربوط به طبقه سرویس را اجرا میکرد. کاربران از طریق شبکه به نرمافزاری که بر روی سرور در حال اجرا بود، دسترسی داشتند. به این چیدمان و معماری «برنامهنویسی دو طبقه کلاینت-سرور= two tier client-server programming» گفته میشود. این معماری سبب تغییر از رایانش منولتیک به رایانش شبکه محور شد و کاربران را توانمند ساخت تا بتوانند بطور همزمان به نرمافزار از طریق شبکه دسترسی داشته باشند. در ابتدا، دسترسی به نرمافزار، به شبکههای محلی (LAN) و به حداکثر چند ده کاربر محدود بود.
یکی از مهمترین چالشهای این معماری عدم مقیاسپذیری لازم بر اساس افزایش تعداد کاربران و دسترسی به نرمافزار بصورت گستردهتر بود. در نتیجه به منظور بهبود مقیاسپذیری و دسترسپذیری (برای کسب اطلاعات بیشتر در خصوص ویژگیهای غیرکارکردی و کیفی میتوانید به کتاب software architecture in practice نوشته آقای باس مراجعه کنید )، مدل دو طبقه به معماری سه طبقه بهود داده شد. در معماری سه طبقه منطق کسبوکار از پایگاه داده جدا گردید. ماژولهای منطقی این معماری عبارتند از ماژول ارائه (کلاینت)، ماژول منطق کسبوکار و ماژول دسترسی به داده و پایگاه داده است که هر کدام در ماشینهای جداگانهای اجرا میشوند. بیش از دو دهه این معماری، معماری استاندارد توسعه نرمافزار بود.
توسعه اینترنت تغییرات شگرفی را در نیازمندیهای نرمافزارها ایجاد کرد. یکی از این نیازمندیها دسترسی به نرمافزار بر روی بستر اینترنت و مستقل از موقعیت جغرافیایی بود. این نیازمندی به توسعه نرمافزارهای تحت وب انجامید. به عبارت دیگر میتوان گفت که لایه ارائه اکنون روی بستر اینترنت قابل دسترسی بود. این موضوع بر جنبههای مختلفی از نرمافزار از جمله تعداد کاربران و همزمانی استفاده کاربران از نرمافزار تاثیر گذار بود. روندهایی (ترندهایی) مانند خرید برخط، بانکداری برخط و دولت الکترونیکی برخط، نیازمند دسترسپذیری و مقیاسپذیری بالایی بودند. اندازه شبکه، میزان توزیعشدگی نرمافزار را مشخص میکرد. از طرف دیگر این توزیعشدگی به مبنای توزیع شدن اجزا و مولفههای مختلف نرمافزار نیز بود. در این میان یکسری مشخصه، استاندارد و چارچوبهایی نیز ابداع شدند. فناوریهایی که بر نحوه فراخوانی متدها از راهدور و مدیریت تعاملات بین نرمافزارها، اما با اتصالی کاملا سخت و به شیوه شیگرا تمرکز داشتند. از جمله این فناوریها CORBA، DCOM و RMI بودند.
رشد و پویایی روزافزون نیازمندیها سبب شد که سازمانها به سمت یکپارچهسازی نرمافزارهای خود بروند تا فرایندها و اطلاعات کلی لازم به منظور اجابت نیازمندیهای مشتریان، بصورت یکجا و موثر در دسترس باشد. این موضوع توسط سبک معماری به نام سرویسگرایی یا معماری سرویسگرا، مورد توجه قرار گرفت. معماری سرویسگرا با استفاده از مجموعهای از پروتکلهای ارتباط آزاد XML محور که وب سرویس نامیده میشوند، پیادهسازی میشود.
مفهوم معماری سرویسگرا
اگرچه استفاده از ارتباط توزیعشده شی گرا توسعه نرمافزارها را به شکل قابل توجهی تسهیل کرد، اما این فناوریها نتوانستند پاسخگوی تمامی نیازهای سازمانها باشند. برای روشن شدن این موضوع سناریوی زیر را در نظر بگیرید:
در عمل کسبوکارها، دارای ساختار سازمانی خوشتعریفی هستند که شامل دپارتمانهای مختلفی مانند مالی، جبران خدمات، حسابداری، مدیریت، پشتیبانی و تدارکات، انبار، فروش و غیره هستند. این ساختار به شناسایی افراد با تخصصهای به خصوص و دستهبندی آنها در دپارتمان مربوطه کمک میکند. در این ساختار سازمانی، با اینکه تمامی دپارتمانها در جهت اهداف و برنامههای سازمان عمل میکنند اما هر دپارتمان آزادی لازم را در برخی از تصمیمگیریها دارند. فناوری اطلاعات امروزه توسط تمامی دپارتمانها و بخشها استفاده میشود. دپارتمانها راهکار فناورانه را بر مبنای نیازهای فنی آن دپارتمان، محدودیتهای بودجه و زمان و فناوریهای در دسترس انتخاب میکنند. نکته این جاست که هر دپارتمان به طور مستقل و با در نظر داشتن اهداف همان دپارتمان راهکارهای فناورانه را انتخاب میکند. نتیجه این راهکارها شرایط زیر است:
یکی از مسائل اصلی مرتبط با نرمافزارهای تجاری ناهمگونی برنامهها است. به این دلیل به این برنامهها سیلوها یا جزیرههای اطلاعاتی گفته میشود. واکشی اطلاعات کاربردی و تصمیمگیری بر مبنای این اطلاعات کار بسیار دشواری است. ناهمگونی برنامههای کاربردی مانع تعامل با یکدیگر و همچنین مانع اشتراک و استفاده مجدد از ماژولهای کارکردی توسعه داده شده و مهمتر از همه اینها مانع یکپارچهسازی اطلاعات میشود.
این چالش توسط معماری سرویسگرا پاسخ داده شد. معماری سرویسگرا بر توسعه برنامههای کاربردی بر مبنای اجزا نرمافزاری مستقل که دارای APIهای خوش تعریف هستند (که سرویس نامیده میشوند) و از طریق پروتکلهای استاندارد ارتباطی در تمامی شبکه قابل دسترسی هستند، تاکید دارد. هدف اصلی معماری سرویسگرا ایجاد تعاملپذیری بین نرمافزارهای کسبوکار و ایجاد ارتباط برنامههای کابردی با یکدیگر است. این برنامهها را میتوان با تکنولوِژی استکهای مختلف توسعه داد.
مفهوم سرویسگرایی، مفهوم جدیدی نیست. همانطور که اشاره شد ماژولهای توزیعشده زیادی امکان تعاملات بین برنامههای کاربردی ناهمگون را فراهم کردهاند. مانند Common Object Request Architecture که به اختصار CORBA نامیده میشود یا Distributed Component Object Model که DCOM نامیده میشود. اما CORBA، DCOM، RMI و غیره در اصل برای استقرار معماری سرویسگرا توسعه داده نشده بودند. این فناوریها در اصل برای برنامههای کاربردی شی گرا توزیعشده بودند. نکته دیگر آن است که این فناوریها بر مبنای اتصالات قوی برای برنامههای کاربردی توزیع شده بر بستر شبکه بودند در حالی که معماری سرویسگرا بر اتصالات سست بین برنامههای کابردی به منظور ایجاد تعاملات بین برنامهای و دستیابی به فرایندهای یکپارچه کسبوکار تمرکز دارد.
وب سرویس
وب سرویسها مجموعهای از پروتکلهای ارتباط باز XML محور هستند که برای پیادهسازی معماری سرویسگرا توسعه داده شدهاند. هدف اصلی آنها ایجاد امکان تعامل بین برنامههای کاربردی بر مبنای اتصالات سست و پیام محور با استفاده از پروتکلهای استاندارد است. این تکنولوژی استک شامل Simple Object Access Protocol که به اختصار SOAP گفته میشود، Universal Description Discovery and Integration (UDDI) و Web Service Description Language (WSDL) است که از HTTP به عنوان پروتکل ترانسپورت استفاده میکند.
چرا به وب سرویس نیاز داریم؟
سوالی که در ذهن خطور میکند این است که اگر وب سرویسها صرفا امکان تبادل پیام را بین نرمافزارها فراهم میکنند، چه دلیلی دارد که از آنها استفاده کنیم؟ پاسخ به این سوال در این حقیقت نهفته است که تعاملات بسیاری بر روی بستر وب روی میدهد. نقطه قوت اصلی وب سرویسها این است که از HTTP به عنوان پروتکل ترانسپورت استفاده میکند. بنابراین ارسال و دریافت پیام بر روی HTTP بر روی اینترنت بسیار ساده میشود.در این حالت برنامههای کاربردی به زیرساخت مجزا نیاز ندارند و از طرف دیگر HTTP با فایروال مشکلی ندارد که البته این موضوع یک شمشیر دو لبه است.
یکپارچهسازی برنامههای کابردی سازمان (Enterprise Application Integration)
سناریو قسمتهای قبل را به خاطر بیاورید. واحد فروش از برنامه اتوماسیون فروش که با .NET توسعه داده شده است استفاده میکند، واحد تدارکات و پشتیبانی، از نرمافزار پشتیبانی زنجیره تامین که با J2EE تولید شده است، استفاده میکند و برنامه کاربردی هسته شرکت نیز از برنامهای که با COBOL نوشته شده است، تشکیل شده است. ماهیت سازمان ایجاب میکند سیستمها و نرمافزارهای مستقلی، سرویسهای متنوعی را به سازمان به منظور انجام وظایف روتین و روزانه کسبوکار، ارائه کنند.
اگرچه سازمانها فعالیتهای روزمره خود را با استفاده از هر کدام از این برنامهها بدون مانع انجام میدهند، اما بازدهی کلی سازمان ممکن است بسیار پایین باشد. زیرا این برنامهها از یکدیگر مستقل هستند و با هم ارتباطی ندارند. اما به دلیل ناهمگونی سیستمعامل، تکنولوژی استک، پروتکلهای ارتباطی و غیره نمیتوانند با یکدیگر ارتباط برقرار کنند. به دلیل عدم ارتباط یا ارتباط ناکافی، برنامهها امکان اشتراک داده و پردازهها را با یکدیگر ندارند. همانطور که قبلا گفته شد سیلوهای اطلاعاتی در سطح سازمان شکل میگیرد. نگهداشت دادههای همسان دشوار میشود، این موضوع به data inconsistency و loss of integrity میانجامد. از سوی دیگر این عدم ارتباط از خودکارسازی فرایندهای سازمان نیز جلوگیری میکند. در نتیجه عملکرد فرایندهای کسبوکار دچار نقصان خواهد شد، و سازمان توانایی رقابت در بازار را از دست خواهد داد. بنابراین نیاز است که داده و فرایندهای سازمان یکپارچه شوند. دادهها، برنامههای کاربردی مختلف و فرایندهای سازمان از طریق تکنیک EAI یکپارچه میشوند. EAI به دادههای موجود امکان میدهد که بین برنامههای مختلف از طریق ایجاد واسطهای مختلف جریان پیدا کند. این واسطها برای مدیریت حریانهای مختلف داده هستند.
بطور خلاصه به منظور استفاده از مزایای سیستمهای توزیع شده و پیمانهای سازمان باید از فناوریهایی استفاده کند، تا بتواند بر مشکلات این سیستمهای فایق آید:
زمانی که یکپارچهسازی نقطه به نقطه کافی نبود!
قبل از توسعه رویکردهای مبتنی بر EAI، مسائل مرتبط با یکپارچهسازی از طریق یکپارچهسازی نقطه به نقطه مدیریت میشدند. در این مدل یکپارچهسازی یک مولفه کانکتور (برای آشنایی بیشتر با الگوهای طراحی به کتاب Dive into Design Patterns نوشته آقای Alexander Shvets مراجعه کنید) در هر زوج از برنامه یا سیستمی که باید با یکدیگر ارتباط داشته باشند، تعبیه میشد. این کانکتور تمامی نقل و انتقالات داده، یکپارچهسازی و سایر سرویسهای مرتبط با انتقال پیام را که بین زوج مشخصی از مولفهها انجام میشود، بر عهده دارد. این شیوه برای زیرساختهای کوچک که دارای 2 یا 3 سیستم که نیاز به یکپارچهسازی داشتند مناسب است، این مدل به خوبی کار میکند و یک راهکار سبک وزن است. اما اگر حتی یک مولفه، به آن اضافه شود، تعداد ارتباط نقطه به نقطه لازم برای ایجاد یک معماری یکپارچهسازی جامع، بصورت نمایی افزایش مییابد.
یک زیرساخت سه-مولفهای به سه ارتباط نقطه به نقطه نیاز دارد تا بطور کامل یکپارچه باشد. اگر دو مولفه دیگر به آن اضافه شود این عدد به 10 اتصال افزایش مییابد. این افزایش به سطح غیر قابل مدیریتی از پیچیدگی میرسد و زمانی که زیرساخت شامل 8 یا 9 مولفه باشد، تعداد اتصالات به 30 افزایش مییابد بنابراین یکپارچهسازی نقطه به نقطه دیگر یک انتخاب مناسب نخواهد بود. این اتصالات باید بصورت مستقل توسعه داده شوند و با تغییرات ناشی از ورژن، مقیاسپذیری و غیره باید نگهداشت شوند یا حتی با هزینه زیادی برای انطباق با سایر مولفهها باید خریداری شوند. بنابراین مناسب نبودن این رویکرد برای سناریوهای پیچیده سازمانی کاملا واضح است.
رویکرد EAI در مواجهه با یکپارچهسازی
برای جلوگیری از پیچیدگی و اشکلاتی که ممکن است در یکپارچهسازی با رویکرد نقطه به نقطه روی دهد، مدلهای مختلفی از EAI به منظور متمرکزسازی و استاندارد نمودن یکپارچهسازی کامل یک زیرساخت وجود دارد. به جای آن که هر برنامه نیازمند یک کانکتور مستقل برای اتصال به یک کانکتور دیگر باشد، مولفههای یک زیرساخت EAI محور از روشهای استانداردی برای اتصال به یک سیستم مشترک استفاده میکنند که مسئول یکپارچهسازی، مبادله پیام و ایجاد قابلیتهای مرتبط با قابلیت اعتماد به کل شبکه است. به عبارت دیگر EAI مسئله یکپارچهسازی سیستمهای پیمانهای را با در نظر گرفتن یکپارچهسازی به عنوان بخشی از وظایف سیستم، مانند هر وظیفه دیگری، حل میکند. EAI تمامی اداپتورها را برای اتصال، موتورهای تبدیل داده را برای تبدیل داده به فرمت مناسب برای استفاده توسط مصرف کننده، موتورهای یکپارچهسازی ماژولار را برای مدیریت سناریوهای پیچیده مسیریابی، و سایر مولفهها را برای ارائه یک رویکرد یکپارچه، به یکدیگر متصل میکند.
در واقع EAI اتصالات بسیار سفت یکپارچهسازی نقطه به نقطه را سست میکند. یک برنامه میتواند بدون دانستن موقعیت، الزامات داده یا استفاده به هر مصرف کننده پیام بفرستد. در واقع تمامی این اطلاعات توسط EAI مدیریت میکند. این نوع از تجرید امکان ایجاد معماری انعطافپذیرتر را فراهم میکند. در این حالت میتوان به راحتی اجزایی را اضافه کرد یا حذف نمود، فقط کافی است که پیکربندی EAI را تغییر داد. راهکارهای ابتدایی EAI ایده یکنواخت سازی یکپارچهسازی را در قالب کارکرد لازم برای یکپارچهسازی در هابهای مرکزی پیادهسازی کردند که به آن دلال یا broker میگفتند.
مدل بروکر
در رویکرد بروکر یک موتور یکپارچهسازی مرکزی، که بروکر یا دلال نامیده میشود، در میان شبکه قرار میگیرد و تمامی انتقال پیامها، مسیریابی و هر عملکرد دیگر بین-برنامهای را انجام میدهد. تمامی ارتباطات بین برنامههای کاربردی باید از این هاب عبور نماید، بنابراین تمامی concurrency داده در کل شبکه توسط هاب انجام میشود. معمولا استقرار مدل بروکر شامل ابزارهای پایش و ممیزی نیز میشود تا کاربران در خصوص جریان پیامهای عبوری از سیستم اطلاعات کافی داشته باشند و بتوانند پیکربندی و مسیریابی بین سیستمها و برنامهها را نیز انجام دهند.
مزایا: این مدل امکان اتصال سست بین برنامهها را فراهم میکند.برنامهها میتوانند بصورت ناهمگام Asynchronous با یکدیگر ارتباط داشته، پیامها را ارسال کنند و بدون آنکه منتظر پاسخ از گیرنده باشند و با سطح تجرید نسبتا بالا، وظایف خود را انجام دهند. امکان پیکربندی از یک مخزن مرکزی فراهم است که به معنای کاهش تغییرات پیکربندی پی در پی است.
معایب: دارای single point of failure، زیرا بروکر مسئول concurrency بین دادههای کاربران، حالتها و تمامی پیامهایی است که از آن عبور میکند. تحت بارهای بزرگ، بروکر تبدیل به گلوگاه پیامها میشود. یک مقصد مرکزی برای تمامی پیامها، امکان استفاده از این روش در فواصل طولانی را پیچیده میکند. استقرار مدل بروکر بسیار سنگین وزن است، شامل محصولات انحصاری است که معمولا فناوریهای یک برند یا فروشنده به خصوص را پشتیبانی میکند. این موضوع زمانی که یکپارچهسازی شامل محصولاتی از فروشندههای مختلف، سیستمهای بومی یا محصولات موروثی باشد که دیگر توسط فروشنده پشتیبانی نمیشوند، مشکلات اساسی را ایجاد میکند.
گام بعدی ESB
استقرار مدل بروکر اقدامی موفقیتآمیز بود، اما اکثریت پروژهها یکپارچهسازی با استفاده از این مدل نهایتا به شکست ختم شد. نبود استانداردهای واضح برای معماری EAI و این واقعیت که بسیاری از راهکارها، انحصاری بودند سبب شد، که محصولات اولیه EAI گران قیمت و سنگین وزن باشند. حتی در برخی از موارد تا زمانی که کل سیستم از برنامههای همگون ساخت یک یا چند شرکت به خصوص نمیبود، کار نمیکرد. یک مطالعه که در سال 2003 منتشر شده بود، تخمین میزد که 70 درصد از پروژههای یکپارچهسازی به دلیل نقص در راهکارهای بروکر اولیه به شکست ختم شدند.
معماری گذرگاه (Bus) - رویکردی جدید به EAI
برای حل مشکلات ناشی از هاب بروکر، یک مدل جدید از EAI ظهور کرد-Bus. این معماری همچنان از مولفه مسیریابی مرکزی برای تبادل پیامها از سیستم به سیستم استفاده میکند. معماری Bus بار کاری محوله بر یک مولفه را، از طریق توزیع وظایف یکپارچهسازی به سایر بخشهای شبکه، کاهش میدهد. این مولفهها از طریق پیکربندیهای مختلف به منظور مدیریت هر سناریو یکپارچهسازی، داخل یک گروه قرار میگیرد، در هر جایی از شبکه امکان میزبانی از آنها وجود دارد و حتی میتوان به منظور مقایسپذیری برای سیستمهای بزرگ آنها را duplicate کرد.
تولد گذرگاه سرویس سازمانی (Enterprise Service Bus =ESB)
با تکامل EAI گذرگاه محور، چند کارکرد لازم جدید شناسایی شدند، از جمله میتوان به پردازش امنیت تراکنش، error handling و غیره اشاره کرد. به جای نوشتن کد این ویژگیها در منطق یکپارچهسازی مرکزی، معماری Bus امکان پیادهسازی این کارکرد در قالب مولفههای جداگانه را فراهم میکند. نتیجه نهایی، یک راهکار یکپارچهسازی سبکوزن و سفارشیسازی شده است که اتکاپذیری را تضمین نموده، انتزاع بسیار بالایی از لایه اپلیکیشن دارد، از یک الگوی پیوسته پیروی مینماید و میتوان آن را با حداقل کد اضافی طراحی و پیکربندی نمود و از تغییر در سیستمها در زمان یکپارچهسازی بینیاز است. این ورژن بالغ مدل Bus محور، ESB نامیده شد.
ویژگیهای اصلی ESB
محصولات ESB مختلفی در بازار در دسترس است. از جمله محصولات خارجی میتوان به WebSphere و TIBCO اشاره کرد که در واقع محصولات EAI هستند که برای ESB در واقع refactor شدهاند. برخی دیگر مانند Mule از پایه به عنوان ESB طراحی شدهاند. اما ویژگیهای اصلی تمامی این محصولات یکسان است:
مزایای ESB
آقای مارتین فاولر عبارت «مایکروسرویس» را در سال 2011 در کارگاه معماری نرمافزار اولینبار مستند کرد. آقای فاولر معتقد است که معماری مایکروسرویس شامل مجموعهای از سرویسها است که میتوان آنها را بصورت مستقل پیادهسازی کرد و حول قابلیتهای کسبوکار سازمان دهی کرد، بصورت خودکار پیادهسازی نمود و از نظر زبان و داده از آنها تمرکززدایی نمود. ایده معماری مایکروسرویس آن است که برنامه را از نظر ساخت و نگهداشت با شکستن آن به اجزا کوچکتر سادهتر کرد. نکته بسیار مهم در خصوص مایکروسرویسها آن است که با معماری یک برنامه سروکار دارد و هیچ ارتباطی با معماری سرویسگرا که ارتباط یک برنامه با برنامههای دیگر است، ندارد. اما از نظر به کارگیری سرویس هر دو مشابه هستند.
معمولا نرمافزارهای سازمانی به سه طبقه تقسیم میشوند: طبقه ارائه، طبقه منطق کسبوکار و طبقه دسترسی داده. در اینجا پیمانهبندی برنامهها بر مبنای تخصص تیمهای توسعه است. بطور مثال تیم واسط کاربری با منطق ارائه سروکار دارد، توسعهدهندهها با دانش یک دامنه مشخص با منطق کسبوکار سروکار دارند و توسعهدهندگان پایگاه داده با طبقه دسترسی داده سروکار دارند. از نظر فیزیکی نیز ممکن است در ماشینهای فیزیکی جداگانهای مستقر میشوند. در اینجا دانهبندی پیمانهبندی درشت است. در این پیمانهبندی، منطق ارائه در وب سرور، منطق کسبوکار در سرور برنامه و دسترسی داده و سرور پایگاه داده در ماشین دیگری خواهد بود. نکته اینجاست که تمامی ویژگیها و کارکردهای مربوط به برنامه توسط یک برنامه سمت سرور منولتیک مدیریت میشوند. کد مرتبط با ارائه در قالب یک فایل war ساخته و در یک وب سرور مانند آپاچی تامکت پیادهسازی میشود. به همین ترتیب پیمانهها یا ماژولهای منطق کسبوکار و منطق دسترسی به داده دارای اتصال سفت هستند و ماژولها در قالب یک پکج بطور مثال یک فایل jar ترکیب شدهاند و در سرورهای برنامه مانند BEA Weblogic، و یا IBM Websphere و یا سرور sun مستقر شدهاند. هر طبقه بصورت یک پکج مستقر میشود. توسعه برنامههای سازمانی شامل صدها توسعه دهنده است که بر روی ماژولهای مختلف همان برنامه مشغول کار هستند.
زمانی که تیمها وظایف مربوط به خود را انجام میدهند، استقرار به دو دلیل بسیار دشوار است : اندازه پروژه بزرگ است و زمانی زیادی برای استقرار میطلبد، از آنجایی که تیمهای مختلفی بر روی قسمتهای مختلفی کار میکنند، ممکن است نیاز باشد تا یک تیم دست از کار بکشد و منتظر پایان کار تیم دیگری بماند.
بنابراین این معماری مناسب برنامههایی که به استقرار مداوم برای تحویل پیوسته نیاز دارند مناسب نیست.
چالشهای معماری سنتی
تهاتر (trade-off) در مایکروسرویس
در یک نرمافزار منولتیک، تمامی اجزا در یک جعبه قرار دارند. بنابراین میتوان در کد وابستگی داشت بدون آنکه نگران مسائل مرتبط با استقرار باشیم. تمامی اجزا در زمان استقرار و پیادهسازی یکجا تحویل داده میشوند. اما در معماری مایکروسرویس، اجزا روی شبکه پخش هستند. بنابراین باید زمان بیشتری را اصطلاحا صرف سیمکشی بین مایکروسرویسها کرد تا نرمافزار بطور کامل راهاندازی شود. بخشی از این سیمکشی شامل شناسایی شبکه مایکروسرویسها است و فعالسازی دسترسی مجاز تمامی مایکروسرویسهایی است که معماری مورد نظر را تشکیل میدهند. شناسایی و فعالسازی شامل credentialها و تنظیمات فایروال و روتر در لایه فیزیکی عملیات نیز میشود. بنابراین درست که مایکروسرویسها انعطافپذیری بیشتری را از نظر نگهداشت و بهروزرسانی و غیره ارائه میکننند اما هزینهای که برای این انعطافپذیری بیشتر باید پرداخت شود، پیچیدیگی بیشتر است.
معماری مایکروسرویس منابع بیشتری مصرف میکند. هر مایکروسرویس به محیط runtime و فضای ذخیرهسازی مخصوص به خود نیاز دارد. در برخی سناریوها، یک مایکروسرویس بیش از یک نرمافزار منولتیک به منابع نیاز دارد. از نظر توسعه نیز هر مایکروسرویس نیازمند تیم توسعه، سیستم مدیریت source code، فرایند تست و مجموعه اسکریپتهای استقرار منحصر به خود است. بنابراین مایکروسرویسها برای استقلال هزینه منابع سخت افزار و توسعهای بیشتری را میپردازند.
اجرای نرمافزارهای مبتنی بر مایکروسرویس فقط شامل ایجاد چند سرویس مستقل و پیادهسازی آنها در قالب یک شبکه نیست. برنامهریزی و طراحی آن پیچیدهتر است. پیچیدگیهای مربوط به معماری مایکروسرویس منجر به ایجاد چارچوبهای همنواسازی مانند کوبرنتیز شده است. این چارچوبها فناوری پیچیدهای هستند که منحنی یادگیری آنها قابل توجه است. اما در عین حال امکان اجرای نرمافزارهای بسیار بزرگ را فراهم میکند. معماری مایکروسرویس نیازمند این چارچوبهای پیچیده است به ویژه زمانی که بحث مقیاسپذیری مطرح باشد. مایکروسرویس اجزای متحرک زیادی دارد که امکان fail شدن هر کدام از آنها وجود دارد. بنابراین تهاتر مرتبط با اجرای نرمافزارهای مایکروسرویس بصورت قابل اعتماد پذیرفتن پیچیدگی مربوط به چارچوبهای همنواسازی است.
چگونه معماری مایکروسرویس چالشهای مرتبط با برنامههای منولتیک را بر طرف کرد؟
معماری مایکروسرویس چالشهای مرتبط با برنامههای منولتیک سمت سرور را از طریق شکستن آنها به چندین ماژول تک هدف، خودکار، خودکفا و مستقل که مایکروسرویس نامیده میشوند، برطرف میکند. در معماری مایکروسرویس، پیمانهبندی بر مبنای تخصص تیمهای توسعه نیست، بلکه برمبنای هدف یا بطور دقیقتر یک قابلیت کارکردی است (برای کسب اطلاعات بیشتر میتوانید به کتاب معماری تمیز عمو باب مراجعه کنید). بر خلاف نام مایکروسرویس، مایکروسرویس به اندازه سرویس اهمیتی نمیدهد بلکه ماهیت آن سرویس است که اهمیت دارد.
همانطور که اشاره شد محدودیت برنامههای منولتیک اندازه و اتصالات سفت بین مولفههای آن است، که امکان استقرار مداوم و تحویل مداوم را از برنامه میگیرد. این محدودیت با استفاده از تجزیه برنامه به پیمانهها یا ماژولهای نرمافزاری مستقل دارای اتصال سست و خودکار، تسکین مییابد. همان مثال برنامه خرید بر خط را در نظر آورید.
همانطور که در شکل بالا ملاحظه مینمایید میتوان این برنامه را به ماژولهای احراز هویت، کاتالوگ محصول، سبد خرید، پرداخت و غیره شکست یا تجزیه کرد. بطور معمول هر کدام از این ماژولها را میتوان به عنوان یک مایکروسرویس بصورت مستقل توسعه داد و پیادهسازی کرد.
حال ممکن است این سوال پیش آید که چطور میتوان تجزیه برنامه را انجام داد؟ تجزیه برنامه بر مبنای اصل تک وظیفه بودن (single responsibility principle) انجام میگیرد. همانطور که اشاره شد، هر مایکروسرویس باید تنها یک وظیفه مشخص را انجام دهد. دانهبندی مایکروسرویسها بر مبنای قابلیت کارکردی آنها است. به عبارت دیگر تقسیم برنامه به مایکروسرویسها بر مبنای کارکرد آنها در کسبوکار است و نه کارکرد فنی آنها. تمامی ماژولهایی که یک وظیفه را انجام میدهند باید در قالبت یک مایکروسرویس قرار داد. تجزیه برنامهها باید با دقت انجام شود. زیرا هدف اصلی معماری مایکروسرویس توسعه و استقرار سرویسها در قالب برنامههای مستقل است. اگر تجزیه به درستی انجام نگیرد، وابستگیها قطعا از پیادهسازی مداوم جلوگیری خواهد کرد. هر مایکروسرویس تنها یک وظیفه را ارائه میکند و قرار نیست تمامی فرایندهای کسبوکار را ارائه دهد. برای آن که یک فرایند به درستی توسط مایکروسرویسها ارائه شود باید مکانیزمی وجود داشته باشد تا امکان تعامل مایکروسرویسها بایکدیگر را فراهم آورد.
یک سرویس با سرویس دیگر به دو طریق میتواند ارتباط برقرار کند: ارتباط همگام و ارتباط غیر همگام. پروتکلهای ارتباطی مختلفی برای هر دو نوع ارتباط توسعه داده شدهاند و در دسترس هستند. بطور کلی پروتکلهای REST برای ارتباط همگام استفاده میشوند. یک راه استفاده از فراخوانیهای API است. هر سرویس یک end-point دارد که درخواستها را از سرویس دیگر دریافت میکند. بنابراین سرویسها میتوانند از طریق ارسال درخواستهای HTTP با یکدیگر گفتگو کنند.به این نوع ارتباط، ارتباط همگام (synchronous) گفته میشود. یک سرویس به سرویس دیگر درخواست میفرستد و منتظر پاسخ میماند.
از ابزارهای واسطافزاری مانند Rabbit MQ و Apache Kafka برای مدلهای ارتباطی ناهمگام استفاده میشود. علاوه بر این از فرمتهای داده استانداردی مانند JSON، XML و غیره برای سریالایز کردن داده در حین ارتباط استفاده میشود.
راه دیگر برقراری ارتباط بین مایکروسرویسها، استفاده از واسطه پیام (Message Broker) است. این ارتباط ناهمگام (Asynchronous) است. الگوهای رایج: Publish/Subscribe، Point-to-point Messaging.
از واسطههای پیام به عنوان واسط افزار بین مایکروسرویسها استفاده میشود که در آن مایکروسرویس میتواند پیامها را به یک واسطه send/deliver یا منتشر (publish) کند، سایر مایکروسرویسها میتوانند به آن واسطه متصل شده و پیامها را دریافت یا subscribe کنند. هدف اصلی واسطه پیام جداسازی تولیدکننده پیام و دریافتکنند پیام است. با وجود یک واسطه پیام، تولیدکننده پیام از جنبههای ارتباطی رهایی مییابد و بر کار اصلی خود تمرکز میکند. یک واسطه پیام محبوب و سنتی RabbitMQ است که توسط Rabit Technologies توسعه داده شده است.
هر سرویس از طریق API و یک گذرگاه میتواند به API دیگر دسترسی داشته باشد. یک ثبت یا رجیستری سرویس وجود دارد که در آن هر سرویس با خود و موقعیت خود را در آن ذخیره کند. کلاینتی که میخواهد از سرویسهای در دسترس استفاده کند، باید این سرویس رجیستری را چک کرده، موقعیت سرویس را یافته و از طریق API از آن سرویس استفاده کند. یک بخش بسیار مهم از برنامههای مبتنی بر معماری مایکروسرویس گذرگاه API است. گذرگاه API را نباید با API هر یک از مایکروسرویسها اشتباه گرفت. هر مایکروسرویس واسط API خود را دارد بطوری که سایر سرویسها میتوانند از طریق شناسایی موقعیت سرویس از سرویس رجیستری، بطور مستقیم از آن سرویس استفاده کنند. در داخل یک برنامه این نوع ارتباط مستقیم به نظر به بهبود عملکرد کمک میکند. اما اگر یک کاربر از بیرون برنامه به خواهد به یک سرویس دسترسی داشته باشد، فراخوانی آن سرویس از طریق ارسال چندین درخواست بر روی شبکه خارجی، امری دشوار خواهد بود و بر عملکرد کلی سیستم تاثیر منفی خواهد داشت. بنابراین در عمل از یک گذرگاه API استفاده میشود تا یک نقطه ورود مشخص برای برنامه ایجاد شود تا کلاینتها بتوانند از طریق آن به سرویسهای سیستم دسترسی داشته باشند. گذرگاه API معماری داخلی سیستم را محصورسازی encapsulate میکند و با توجه به نیازهای هر کلاینت آن را اصلاح مینماید. از جمله وظایف گذرگاه API میتوان به موارد زیر اشاره کرد:
· درخواست مسیریابی،
· تجزیه،
· مبدل پروتکلها،
· احزار هویت،
· پایش،
· و load balancing،
· و caching،
· و shaping و مدیریت درخواستها،
· و در نهایت مدیریت درخواستهای static.
اگرچه گذرگاه API تمامی کارکردهای بالا را در اختیار کلاینت قرار میدهد، اما خود گذرگاه در واقع یک مولفه است که باید توسعه داده شود، پیادهسازی شود و به درستی مدیریت گردد. اگر گذرگاه API بیش از حد بزرگ شود، خود به گلوگاه معماری مایکروسرویس تبدیل میشود. بنابراین باید طراحی سبک وزنی داشته باشد و تنها محدود به کارکردهای اصلی لازم باشد.
مقیاسپذیری:
مقیاسپذیری مقیاسی از توانایی سیستم در اضافه کردن منابع به منظور مدیریت میزان متغییر از درخواستها است. مقیاسپذیری افقی ( که الاستیسیته نیز نامیده میشود افزودن منابع به واحدهای منطقی مانند سرورهای کلاستر) و مقیاسپذیری عمودی (افزودن منابع به واحدهای فیزیکی مانند افزایش حافظه) دو نوع از مقیاسپذیری هستند. مقیاسپذیری افقی مهمترین خاصیت معماری مبتنی بر میکروسرویس است، زیرا ساختار منولتیک را به مایکروسرویسهای مستقل تجزیه میکند و به اینستنسهای مایکروسرویس امکان مقیاسپذیری را میدهد.
دو تاکتیک رایج برای مقیاسپذیری وجود دارد: horizontal duplication و vertical decomposition.
تکثیر افقی Horizontal duplication:
یک تاکتیک برای مقیاسپذیری است که بر مبنای تئوری محور xهای مکعب مقیاس نرمافزار آبوت و دیگران تعریف شده است. این تاکتیک راهنمایی برای افزایش یا کاهش اینستنسهای مایکروسرویس بر اساس میزان تغییر درخواستها، است. رهیافتهای این تاکتیک عبارتند از مقیاسپذیری خودکار واکنشی و مقیاسپذیری خودکار فعال. بیشتر روشهای واکنشی بر مبنای قوانین مبتنی بر آستانه (حد) هستند، که زمان مقیاسپذیری مایکروسرویسها را مشخص میکنند. مقیاسپذیری خودکار فعال امکان مقیاس کردن منابع بر مبنای باری که ممکن است در آینده ایجاد شود را فراهم میکند.
هدف اصلی Horizontal Duplication مشخص کردن تعداد instanceهای لازم از هر مایکروسرویس است تا سطح مورد نظر از سرویس را اجابت کند. لازم است که معماری مایکروسرویس در مقایس بارهای غیرقابل پیشبینی واکنش مناسب داشته و عرضه instanceهای مایکروسرویس را مطابق تقاضا نگه داشته و از سوی دیگر هزینه را به حداقل رساند. در مقابل گاهی اوقات میتوان بارکاری سیستم را بر مبنای دادههای تاریخی پیشبینی نمود.
مقیاسپذیری خودکار واکنشی: یک مقیاس کننده تصمیم میگیرد که با توجه به آستانه بالا و پایین و با توجه به اطلاعاتی که از پایشهای دورهای به دست میآید (مانند شدت بارکاری، میزان استفاده از CPU، تاخیر HTTP، گذردهی HTTP یا متریکهای مرتبط با صف پیغامها)، مقیاس را انجام دهد. از آنجایی که مایکروسرویسها بصورت متناوب تغییر میکنند، مقیاس کننده باید امکان اصلاح آستانه بالا و پایین را به فرآیند انطباق بدهد.
مقیاسپذیری خودکار فعال: فرآیند آن عبارتند از: 1. پیشبینی بارکاری از دادههای تاریخی به منور یافتن تعداد درخواستها برای هر مایکروسرویس، 2. تبدیل درخواستها به منابع لازم (بطور مثال هسته پردازنده مرکزی و حافظه) به منظور رعایت مفاد SLA، 3. انطباق تقاضا با عرضه منابع لازم به منظور تضمین وجود منابع کافی و همچنین مقرون به صرفه بودن مقیاسپذیری. معمولا از یک الگوریتم بهینهسازی برای یافتن مجموعهای که بیشترین احتمال و کمترین هزینه برای منابع را دارد استفاده میشود.
مقیاسپذیری خودکار فعال دو محدودیت دارد: 1. باید قوانین مبتنی بر آستانه را برای مسائل مدیریت بیش از حد و کمتر از حد تعریف کرد. قوانین در این بافت شامل شرط و اقدامی که باید انجام داد است. شرط شامل یک آستانه بالا و پایین برای متریک عملکردی است که بر مبنای آن مقیاسکننده برای مقیاس instanceهای مایکروسرویس تصمیمگیری میکند. 2. قوانین مبتنی بر آستانه نباید همواره ثابت باقی بماند. برای مایکروسرویسها این قوانین معمولا سفارشی میشوند و بنابراین ممکن است که بر عملکرد اثر بگذارند. از الگوریتمهای اوریستیک برای بهینهسازی هر متریک استفاده میشود.
پیشبینی بارکاری در راهکارهای مقیاسپذیری خودکار فعال به تحلیل دادههای تاریخی بستگی دارد. سیستمها باید برای مدت مشخصی کارکنند تا دقت پیشبینی تضمین شود. سیستم جدیدی که دادههای تاریخی ندارد باید از شبیهسازی برای این منظور استفاده کند.
وابستگی: تاکتیک Horizontal Duplication به شدت به تاکیتک Vertical Decomposition مربوط است، بطوری که به رسیدن به واحد مقیاسپذیر (مایکروسرویسها) کمک میکند. علاوه بر این این تاکتیک به پایشپذیری به منظور ارائه اطلاعات لازم برای تصمیمگیری در خصوص پیکربندی آستانه و عملیاتهای مقیاس در زمان استفاده از رویکرد مقیاسپذیری خودکار واکنشی نیز وابسته است.
تجزیه عمودی Vertical Decomposition:
تاکتیک تجزیه عمودی تجزیه منولیت را به مجموعه از مایکروسرویسهای مناسب شامل پایگاههای داده به منظور دستیابی به مقیاسپذیری بالاتر و مستقل تر را فراهم میکند. با سه رویکرد میتوان تجزیه عمودی را پیادهسازی کرد: اتصال منطقی، اتصال سمانتیک و اتصال مشارکتی.
با توجه به محور Y مکعب مقیاس نرمافزار کاربردی آبوت، مقیاسپذیری را میتوان از طریق جداسازی مسئولیتها، عملیات و داده بهبود داد، به عبارت دیگر مایکروسرویسها را باید بصورت عمودی تجزیه کرد تا استفاده موثری از منابع داشت. به عبارت دیگر، تجزیه سرویس مناسب، یک پیشنیاز برای مقیاسپذیری معماری مایکروسرویس است. همانطور که اشاره شد برای پیادهسازی تجزیه عمودی میتوان رویکردهای زیر را اتخاذ نمود:
زمانی که از تاکتیک تجزیه عمودی استفاده میشود، تصمیمات به منظور یافتن دانهبندی مناسب مایکروسرویسها برای ایجاد توازن بین مقیاسپذیری و عملکرد، باید با دقت اتخاذ شوند. انسجام بالا و اتصال شل به منظور تعیین اندازه مایکروسرویسهای کاندیدا باید مورد توجه قرار بگیرند. مایکروسرویسهای با دانهبندی کوچک و اتصال شل، سبب بهبود استفاده از منابع و کمک به صرفه جویی در هزینههای سیستم از طریق مقیاسپذیری مستقل سرویسهای مشخص به جای کل سیستم میشود. اما این موضوع به این معنی نیست که مایکروسرویسهای با اندازه کوچک لزوما بهتر هستند. مایکروسرویسهای بیش از حد کوچک سبب افزایش تعداد سرویسها و افزایش تعاملات بین مایکروسرویسها در شبکه میشود که تاثیر منفی بر عملکرد دارد، زیرا زمان پاسخ در مدیریت ارتباطات سرویسها طولانیتر میشود. همانطور که قبلا اشاره شد تاکتیک تجزیه عمودی پیشنیاز تاکتیک تجزیه افقی است.
عملکرد:
عملکرد مقیاسی از توانایی سیستم به منظور اجابت الزامات مرتبط به زمان در پاسخ به یک رویکرد است. عملکرد یکی از ویژگیهای کیفی حیاتی برای مایکروسرویسهای توزیع شده در معماری مایکروسرویس است، که معمولا از مکانیزمهای سبکوزن و مبتنی بر REST برای ارتباط بین مایکروسرویسها استفاده میکند. تخصیص انواع منابع با میزانهای متفاوت (بطور مثال ماشینهای مجازی و کانتینرها) بر روی گذردهی یا زمان پاسخ به درخواستهای به خصوص، اثر گذار است. از سوی دیگر تناوب و پیچیدگی بین مایکروسرویسها در شبکه میتواند مستقیما بر عملکرد سیستمها مبتنی بر معماری مایکروسرویس اثرگذار باشد. باید یک trade-off بین مقیاسپذیری و عملکرد انجام شود. مایکروسرویسهای با اندازه کوچک ممکن است سبب افزایش مقیاسپذیری شوند، اما همچنان میتوانند عملکرد را کاهش دهند. دلیل این امر تعاملات بین مایکروسرویسها است. در مقابل، میتوان عملکرد را از طریق ادغام دو مایکروسرویس با یکدیگر و کاهش ارتباط بالادستی و البته با هزینه کاهش مقیاسپذیری، بهبود داد.
تاکتیکهای عملکردی برای معماری مایکروسرویس شناسایی شده را میتوان به گروههای زیر تقسیمبندی کرد: مدیریت و تخصیص منابع، load balancing، کانتینرسازی و profiling.
مدیریت و تخصیص منابع:
رایجترین تاکتیک در مدیریت عملکرد، مدیریت و تخصیص منابع است، که در سمت پاسخ اعمال میشود تا بتوان از منابع در دسترس استفاده موثرتری در مدیریت درخواستها داشت. این تاکتیک مشابه تعریف تاکتیکهایی است که توسط باس بطور مثال افزایش منابع و برنامهریزی، ارائه شده است. بیشتر مطالعاتی که انجام شده است در تلاش برای بهبود عملکرد از طریق مدیریت و تخصیص منابع به منظور دستیابی به عملکرد بهینه مایکروسرویسها بودهاند.
باس معتقد است که تقاضای برای منابع سیستمی قابل کنترل نیست. تحت این شرایط، مدیریت موثر این منابع در سمت پاسخ، برای عملکرد حیاتی است. مدیریت و تخصیص منابع بهینه، سبب میشود که منابع بطور موثرتری با یکدیگر برای درخواست به تقاضاها عمل کنند در نتیجه عملکرد بهتر از طریق throughput بهتر و زمان پاسخ کوتاهتری خواهند داشت. برای استفاده از این تاکتیک، یک مدل عملکردی تحلیلی بر مبنای رفتار سیستمها به منظور انجام تحلیل what-if و رویکردهای برنامهریزی منابع بطور سیستماتیک برای مایکروسرویسهای با مقیاس بزرگ با اهداف بهینهشده، طراحی میشود. زنجیره زمانی پیوسته سه بعدی مارکف و شبکههای پتری تصادفی سیال مثالهایی از این دست هستند. مدل عملکردی شامل گامهایی برای پاسخ به تقاضاها از سوی کاربران، سرویسهای دیگر است و اهداف یا سنجههای عملکردی را محاسبه میکند: تاخیر، هزینه، میزان استفاده از منابع، قابلیت اتکا یا زمان تعمیر، و غیره. بر مبنای مدل عملکردی، یک موتور همنواساز برای مدیریت و تخصیص منابع مانند مایکروسرویسها یا کانتینرها، ماشینهای مجازی یا فیزیکی و استفاده از رویکردهای به خصوص، لازم است. از آنجایی که مدیریت و تخصیص منابع را میتوان به عنوان یک مسئله کامل NP دید، آن را میتوان از طریق رویکردهای نوگرایی مانند الگوریتم ژنتیک و انواع آن مانند NSHA-II که برای بهینهسازیهای چند هدفه مناسب هستند، حل کرد.
در این تاکتیک، مدیریت و تخصیص منابع را میتوان از طریق ترکیب متغیرهای به خصوصی بدست آورد. برای دانستن این که کدام ترکیب از متغیرها، ترکیب بهتری است، یک رویکرد انجام چند آزمایش و شبیهسازی با راهکارهای متفاوت است. اما شبیهسازی که احتمالات متفاوت را در نظر میگیرد زمانبر هستند. بنابراین تقریبهای مناسب از بارکاری لازم است تا چرخه بازخور و تولید معماری جدید مایکروسرویس را بر مبنای متغیرهای موجود و مورد انتظار سیستم، خودکار سازد. البته لازم به ذکر است که اثربخشی این تاکتیک توسط الگوریتم مورد استفاده محدود میشود.
مطالعات بسیاری مدیریت و تخصیص منابع را به تاکتیک Horizontal Duplication به منظور مقیاس کردن و تنظیم منابع متکی میدانند. بطور مثال بر مبنای مدل عملکرد، کانتینرها و ماشینهای مجازی را میتوان توسط یک مدیر مرکزی که مسئول تصمیمگیری در خصوص سطح مقیاس کانتینرها (تعداد آنها) و ماشینهای مجازی، تخصیص کانتینرها در نوع مناسب ماشینهای مجازی و تخصیص ماشینهای مجازی در ارائه دهنده ابر مناسب ، همنوا ساخت. یک الزام مهم برای موتور همنواساز یا مدیر این نوع تاکتیک آن است که تمامی سنجههای عملکردی را بتوان ردگیری کرد. تحت این شرایط تاکتیکهای پایش برای تنظیم پارامترها و اندازهگیری عملکرد لازم هستند.
توازن بار Load Balancing:
این تاکتیک بار ورودی بر روی هر مایکروسرویس را در میان instanceهای مختلف آن توزیع میکند. با استفاده از این روش تقاضاها را میتوان طوری پاسخ داد که سرعت و ظرفیت استفاده از منابع را حداکثر سازد و تضمین کند که به هیچ سرویسی بیش از اندازه بار تحمیل نشود. زیرا این موضوع بر روی عملکرد تاثیر منفی دارد.
در معماری مایکروسرویس، به تقاضاهای کاربران، توسط مجموعهای از instanceهای مایکروسرویس که یک زنجیره را تشکیل میدهند، سرویس داده میشود. بار بالا بر روی یک instance مایکروسرویس ممکن است فرایند تقاضا را مختل نموده و عملکرد سیستمهای مبتنی بر معماری مایکروسرویس را کاهش دهد. به عبارت دیگر تغییر توزیع بار در یک instanceمایکروسرویس و مجبور کردن instanceها به مدیریت تقضاهای کاربر به صورت موازی، به مدیریت چالش عملکرد معماری مایکروسرویس کمک میکند.
به منظور پیادهسازی Load Balancing یک نرمافزار کاربردی باید بتواند بار روی یک سرویس را بین instanceهای مختلف توزیع نماید. این وظیفه Load Balancer است. این مولفه توزیع بار متوازن را از طریق راهکارهای زیر امکانپذیر میسازد:
هر کدام از این شیوههای load balancing محدودیتهای خود را دارند. برای load balancer متمرکز نیاز است که load balancer در سمت سرور، حالت push به سمت کلاینت را ذخیره کند، که این موضوع خود بار اضافی را علاوه بر حجم انبود درخواستهای کلاینتها به load balancer وارد میکند. از سوی دیگر load balancing توزیع شده بار ذخیرهسازی را کاهش میدهد زیرا کلاینتها اطلاعات مفید را بصورت محلی به منظور پشتیبانگیری یا بازیابی ذخیره میکنند. اما pull های متناوب و فعال کلاینتها لزوما به بازیابی داده جدید نمیانجامد، در نتیجه پهنای باد هدر میرود. پیچیدگی دیگر این روش، هماهنگی بین چندین کلاینت است.
سرویس مش راهی برای کنترل اجزای مختلف یک برنامه است که با یکدیگر تبادل داده دارند. برخلاف سایر سیستم مدیریت ارتباط ، سرویس مش یک لایه زیرساخت اختصاصی است که داخل برنامه ساخته میشود. این لایه زیرساختی میتواند کارکرد سایر اجزای برنامه و تعاملات بین آنها را مستند کرده و در نتیجه ارتباط را بهینه کرده و از افزایش downtime برنامه جلوگیری کند.
هر سرویس برای ارائه آن چه که کاربر میخواهد به سایر سرویس متکی است (نه وابسته!). برای مثال همین برنامه خرید برخط، اگر کاربر بخواهد خریدی را انجام دهد، ابتدا باید از موجودی آن کالا اطلاع یابد. بنابراین سرویس ارتباط با پایگاه داده انبار باید با صفحه وب محصول و صفحه وب محصول باید با سبد خرید برخط کاربر ارتباط داشته باشد. برای ایجاد ارزش برای کاربر، فروشنده ممکن است سرویسی را بسازد که به کاربر توصیههای حین خرید را نیز ارائه کند.این سرویس جدید با پایگاه داده محصولات برای ارائه توصیه ارتباط برقرار میکند اما با پایگاه داده انبار و صفحه وب محصولا نیز ارتباط دارد. همانطور که مشاهده میشود سناریو ارائه شده داره اجزا متحرک بسیار و دارای قابلیت استفاده مجدد است. هر سرویس برای آنکه بتواند وظیفه خود را انجام دهد، باید داده را از چندین سرویس دیگر درخواست کند. اما اگر برخی سرویسها در این میان دچار ازدحام شوند، چه اتفاقی میافتد؟ در اینجا نقش سرویس مش مشخص میشود-سرویس مش درخواستها را به سرویس دیگر ارجاع میدهد.
معماری مایکروسرویس امکان ایجاد تغییرات در سرویسها بدون نیاز به پیادهسازی کامل را به توسعه دهندگان میدهد. برخلاف سایر معماریها، هر مایکروسرویس توسط تیمهای کوچکی ساخته میشوند که ابزار و زبان برنامهنویسی را خودشان انتخاب میکنند. بنابراین مایکروسرویسها بصورت مستقل ساخته میشوند، با یکدیگر ارتباط برقرار میکنند و اگر خرابی روی دهد تنها مربوط به همان مایکروسرویس است و به دیگر اجزا برنامه سرایت نمیکند. وجود ارتباط بین سرویسهاست که معماری مایکروسرویس را ممکن میسازد. منطق حاکم بر ارتباط را میتوان بدون وجود لایه سرویس مش در داخل هر مایکروسرویس کد کرد اما همانطور که در بالا اشاره شد، برای برنامههای بزرگ این امر امکان پذیر نیست.
سرویس مش کارکرد جدیدی را به محیط runtime برنامه اضافه نمیکند. برنامهها همواره به قوانینی نیاز داشتند که مشخص شود درخواست چگونه از مبدا به مقصد برسند. آن چیزی که سرویس مش را متمایز میسازد، جدا کردن منطق حاکم بر ارتباط سرویس با سرویس از سرویسها و قرار دادن آن در لایه زیرساخت بصورت انتزاعی و تجریدی است. به این منظور، سرویس مش در قالب آرایهای از پروکسیهای شبکه ساخته میشود. در سرویس مش، درخواستها بین مایکروسرویسها از طریق پروکسیهایی که در لایه زیرساخت قرار گرفته است، مسیریابی و هدایت میشوند. به همین دلیل به هر یک از این پروکسیها که سرویس مش را ایجام میکنند sidecars نیز گفته میشود، زیرا به جای آنکه داخل هر سرویس باشند در کنار سرویس قرار دارند. این پروکسیها در کنار یکدیگر شبکه مش را ایجاد میکنند.
بدون داشتن سرویس مش، منطق حاکم بر ارتباطات بین سرویسها باید در هر سرویس کد شود، یعنی توسعه دهنده توجه کمتری به اصل داستان و اهداف کسبوکار دارد! همچنین در این حالت تشخیص نقص در ارتباط دشوارتر میشود زیرا منطقی که بر ارتباط بین سرویسها حاکم است در داخل هر سرویس پنهان شده است. هر سرویس جدیدی که به برنامه اضافه میشود و یا یک instance از آن سرویس در کانتینر ایجاد میشود، محیط ارتباط پیچیدهتر شده و نقاط شکست جدیدی به سیستم اضافه میشود. در یک معماری مایکروسرویس پیچیده، یافتن مکان نقصها دشوار خواهد شد.
از سوی دیگر، سرویس مش جنبههای مختلف ارتباط سرویس-به-سرویس را در قالب متریکهای عملکردی ثبت میکند. با گذشت زمان، دادههایی که توسط سرویس مش جمعآوری شدهاند را میتوان برای بهبود کارآیی و افزایش قابلیت اتکا به برنامه به کار برد.
ایستیو Istio یک سرویس مش متن باز است که در لایههای نرمافزار توزیع شده موجود قرار میگیرد. بستری یکنواخت و کارآمد برای امن کردن، اتصال و پایش سرویسهاست. راهی برای load balancing، احراز هویت سرویس به سرویس، و پایش است بدون آنکه نیاز به تغییر در کد سرویسها باشد.یکی از ویژگیهای ایستیو کنترل پلین آن است. اما Control plane آن چه ویژگیهایی دارد؟
یکی از ویژگیهای بسیار مهمcontrol plane مربوط بهIstio اجرا بر روی کوبرنتیز است. میتوان نرمافزارهایی که بر آن مستقر شدهاند را به مش اضافه نمود و مش را به سایر خوشهها، ماشینهای مجازی و حتی end-pointهای خارج از کوبرنتیز نیز گسترش داد.
کوبرنتیز یک سکوی همنواسازی و مدیریت کانتینر متن باز است که پیادهسازی کانتینرها، تخصیص منابع به آنها، بررسی سلامتی و پایش، تکثیر و مقیاس خودکار کانتینرها، و load balancing، کشف سرویس و غیره را خودکارسازی و مدیریت میکند. اجزای مختلف کوبرنتیز را در شکل زیر ملاحظه مینمایید:
از نظر مفهومی کوبرنتیز ار مجموعهای از نودها که هر یک نقش متفاوتی دارد تشکیل شده است. کنترل پلین بر روی نود اصلی شامل سرور API، مدیر کنترلر و برنامه ریز scheduler است. سرویس API موجودیت مدیریت مرکزی است و تنها مولفهای که بطور مستقیم با آن صحبت میکند مولفه ذخیرهسازی توزیع شده etcd است که وظایف آن عبارتست از:
سرور API- از API برای انجام عملیاتهای CRUD (create, read, update, delete) بر روی منابع کلاستر استفاده میکند. اعتبارسنجی درخواستها، اجرای منطق کسبوکار در مولفههای مختلف و نگهداشت حالت نتیجه در etcd از دیگر کارکردهای آن است. سرور API خارج از کلاستر نیز برای کلاینتها در دسترس است تا بتوانند کارهای مدیریتی نیز انجام دهند. etcd نیز یک ذخیرهساز توزیع شده است که تمامی حالات کلاسترها در آنجا نگهداری میشود.
برنامهریز Scheduler- مسئول مراقبت از پادهای بدون برنامه است و آنها برای اجرا بر روی نودها مشخص با یکدیگر ترکیب میکند. برنامهریز بطور خودکار کانتینرها را برای اجرا بر روی نودها مشخص باتوجه به منابع در دسترس و الزامات تکثیر کانتینرها، برنامهریزی میکند. برنامهریز میزان منابع در دسترس بر روی نودها را میداند و بسته به این منابع و میزان تقاضا نودها را برای اجرای پاد انتخاب میکند.
مدیر کنترلر-مسئول اجرای انواع کنترلرها است. کنترلرها بر حالت کلاسترها را نظارت کرده و اقدام اصلاحی را به منظور برگرداندن کلاستر به حالت مطلوب انجام میدهند. کنترلر نود مسئول پایش نود و انجام اقدام اصلاحی در صورت down شدن آن نود است. کنترلر تکثیر مسئول پایش تعداد پادهای در حال اجرا است و در صورت down شدن پادها، ایجاد پادهای جدید را برنامهریزی میکند تا حالت مورد نظر تکثیر ایجاد شود.
کوبلت kebelet-عاملی است که در هر نود کلاستر اجرا میشود و پاد و API نود را برای اجرای کانتینرها پیادهسازی میکند. مسئول پایش کانترها و تضمین اجرای آنها است. مشخصههای هر پاد را دریافت میکند و کانتینرها را بر مبنای آن اجرا میکند.
کوب پروکسی kube proxy- مولفهای است که امکان تجرید سرویس را فراهم میکند. درخواستهای کلاینتها را پروکسی نمود و آن را به سمت پادهای نود به منظور توازن بار هدایت میکند.
پاد pod- واحد پایه کوبرنتیز است که ایجاد و پیادهسازی میشود. کانتینرهای برنامهها را بر روی نود اجرا میکند. پادها اشیا جهش پذیر هستند که ایجاد و سپس نابود میشوند. یک پاد نشان دهنده یک instance از برنامه است. میتوان آن را بر روی نودهای مختلف تکثیر نمود تا دسترسپذیری بالا و مقیاسپذیری الاستیک را ارائه داد. در زمان تعریف پاد، تخصیص منابع رایانش برای هر کانتینر مشخص میشود.
سرویس- از آنجایی که پادها ایجاد و نابود میشوند، باید مکانیزمی برای دسترسی به برنامه از طریق یک endpoint وجود داشته باشد. سرویس انتزاعی است که مجموعه منطقی از پادها را تعریف نموده و ترافیک کلاینت را به سمت آن مسیریابی میکند. پادها را میتوان ایجاد کرد، نابود کرد و بر روی چندین پاد تکثیر کرد اما کلاینتها همچنان میتوانند از طریق سرویسها به پادهای backend دسترسی داشته باشند.
دی ان اس کوب kube DNS- یک سرویس تعبیه شده است که برای اجرا به عنوان یک پاد در کلاستر برنامه ریزی شده است. هر سرویس در کلاستر یک نام DNS دارد. سرویسها را با نام DNS آنها میتوان شناسایی کرد. یک پاد Kube DNS سه کانتینر را در خود اجرا میکند: kubedns، dnsmasq، و healthz. اولی مستر کوبرنتیز را برای تغییرات در سرویسها نظارت میکند و درخواستهای جستجوی سرویس را در حافظه نگه میدارد. دومی به منظور بهبود عملکرد امکان caching را ایجاد میکند و سومی سلامت kubedns و dnsmasq را تحت نظر دارد.
این مطلب بخشی از تمرینات درس معماری نرمافزار دانشگاه شهید بهشتی است.