ارتباط بین سرویس ها در معماری میکروسرویس

در این مقاله قصد داریم که انواع ارتباط بین میکروسیرویس ها و چگونگی برقراری این ارتباطات رو به شما آموزش دهیم. معماری میکروسرویس برخلاف معماری مونولیتیک که بصورت یکپارچه بود دارای سرویس های مختلفی است و این سرویس ها هرچند مستقل از هم هستن ولی نیاز دارند که با هم در ارتباط باشند ما در دوره رایگان آموزش میکروسرویس ارتباط بین میکروسرویس ها را آموزش داده ایم.برای مثال اگر شما بخواهید برای یک فروشگاه نرم افراز بنویسید و از معماری میکروسرویس استفاده کنید این سیستم فروشگاه به زیرسیستم‌های زیر تقسیم می‌شود البته اگر بخواهیم به‌صورت کلی نگاه کنیم در غیر این صورت یک سیستم را می‌توانیم آن‌قدر توسعه دهیم و تقسیم‌بندی کنیم که میکروسرویس‌های آن ده ها یا صدها میکروسرویس را تشکیل دهند اما به طور عمومی یک سیستم فروشگاه به زیرسیستم‌های زیر تقسیم می‌شوند.microserviceاین سرویس‌ها نیاز دارند با یکدیگر در ارتباط باشند اما جدایی از این سرویس‌ها و ارتباط بین آنها یک سیستم میکروسرویس دیگر داریم که لایه UI ما را تشکیل می‌دهد که کاربر ما بتواند از طریق آن از این زیرسیستم‌ها استفاده کند. مثلاً کاربر نهایی نمی‌تواند به‌صورت مستقیم با سرویس محصولات من کار کند، چون سرویس محصولات فقط یک سری API ارائه می‌دهد و یا دیگر سرویس‌ها هم به همین صورت یک سری API ارائه می‌دهند و مخصوص یک نرم‌افزار است و باید یک نرم‌افزار از آنها استفاده کند و به همین منظور ما یک پروژه جدید به جز میکروسرویس‌های تشکیل دهنده یک سیستم باید ایجاد کنیم که به آن لایهٔ UI گفته می‌شود، برای ارتباط کاربر با بقیهٔ سرویس‌ها مانند شکل زیر:uiحالا به جز ارتباط UI با سرویس‌ها خود سرویس‌ها باید با هم ارتباط داشته باشد مثلاً در سبد خرید وقتی می‌خواهیم یک محصول را به سبد خرید اضافه کنیم، یا یک تخفیف را روی سبد خرید اعمال کنیم، باید سرویس سبد خرید با سرویس تخفیف ما ارتباط برقرار کند، و کد تخفیف را بفرستد و چک کند و نتیجه را بیاورد در سبد خرید اعمال کند.یا بعد از اینکه سبد خرید تکمیل شد و میخواهد سفارش را ثبت کند باید سبد خرید با سرویس سفارش ارتباط برقرار کند.سپس خود سرویس‌ها هم با هم ارتباطاتی دارند که ما باید این ارتباطات را برقرار کنیم.و اگر به صورت کلی ما بخواهیم ارتباط بین میکرو سرویس ها را برقرار کنیم دو نوع ارتباط داریم.1)sync یا synchronous2)async یا asynchronousارتباط sync به این صورت است که سرویس مبدأ به‌صورت مستقیم یک API از سرویس مقصد را call می‌کند و منتظر می‌ماند که Response آن را دریافت کند که استفاده از ارتباط sync در معماری میکرو سرویس‌ها خیلی کم است ولی بعضی وقت‌ها مجبوریم از این ارتباط نیز استفاده کنیم که sync معایب بالایی دارد، و ارتباط sync به این صورت است که ما API را که سرویس موردنظر ارائه داده، به‌صورت مستقیم از آن استفاده می‌کنیم، مثلاً اگر سرویس سبد خرید با C# پیاده‌سازی شده باشد با Rest sharp می‌توانیم API تخفیف را صدا بزنیم و کد تخفیف را بفرستیم و نتیجه رو دریافت کنیم، در این حالت سرویس سبد خرید باید منتظر بماند که سرویس تخفیف جواب را برای آن ارسال کند و نمی‌تواند کار دیگری انجام دهد و اما در بعضی مواقع نیاز به چنین ارتباطی نداریم و می‌توانیم از ارتباط‌های async استفاده کنیم و این نوع ارتباط به این صورت است که مثلاً سرویس سبد خرید می‌خواهد یک سفارشی را ثبت کند، اطلاعات را برای سرویس سفارش می‌فرستد و دیگر منتظر نمی‌ماند که سرویس سفارش جواب را ارسال کند و به کار خودش ادامه می‌دهد و هر زمانی که سرویس سفارشی کارش تمام شد اطلاعات را برای سرویس سبد خرید ارسال می‌کند.برای ارتباط async باید از پروتکل‌های دیگر استفاده کنیم، و پیاده‌سازی آن کمی سخت تراست.sync یا Synchronous :مابین سرویس‌ها هم می‌توانیم از روش sync استفاده کنیم مثلاً اگر ما بخواهیم بین سرویس سبد خرید و سرویس تخفیف یک ارتباط برقرار کنیم می‌توانیم از روش Synchronous استفاده کنیم و به این صورت است که در سبد خرید کاربر یک کد وارد کرده و ما نیاز داریم به درون سرویس تخفیف برویم و بررسی کنیم که این کد معتبر است یا نه و اگر معتبر بود ما چقدر و یا چه مبلغ باید از این فاکتور یا سبد خرید کسر کنیم پس ما نیاز داریم کد را بفرستیم به سبد، خرید ویک ارتباط باید ایجاد کنیم در اینجا می‌توانیم از ارتباط سینک و یا ای سینک استفاده کنیم. ارتباط Synchronous را می‌توانیم به‌صورت زیر با http/RestFull انجام دهیم. البته روش‌های دیگری هم وجود دارد که مرسوم‌ترین آنها http/RestFull است.ما درخواستمان را برای یک api از سرویس تخفیف ارسال می‌کنیم و سرویس سبد خرید منتظر می‌ماند و کاری نمی‌تواند انجام دهد.یعنی زمانی که کد را وارد کرد و دکمه ثبت تخفیف را زد این درخواست ارسال می‌شود برای سرویس تخفیف و سرویس تخفیف درون دیتابیس خودش جستجو می‌کند و اطلاعات را آورده و اعتبارسنجی‌ها را انجام می‌دهد و کارهای موردنیاز را درون این سرویس انجام می‌دهد،و بعد Response را برای سبد خرید ارسال می‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌کند و به این صورت سبد خرید می‌تواند یک ارتباط بین خودش و سرویس تخفیف ایجاد کند و دیتای مورد نیازش را به دست بیاورد.اما اگر کمی دقت کنید این روش معایبی دارد مثلاً اگر سرویس تخفیف از دسترس خارج شود در آن لحظه سرویس سبد خرید نمی‌تواند کار خودش را ادامه دهد، یک درخواست ارسال کرده و با شکست مواجه شده. پس نمی‌تواند کار خودش را ادامه دهد، اگر سرویس تخفیف برای تکمیل کردن اطلاعات خودش نیاز داشته باشد با سرویس‌های دیگر ارتباط برقرار کند و این ارتباط طولانی شود تمام این زمان باید سرویس سبد خرید منتظر پاسخ از طرف سرویس تخفیف بماند، و پرفورمنس ما کاهش می‌یابد. البته به این نکته توجه داشته باشید که در بعضی موارد ما مجبوریم از این روش (sync) استفاده کنیم. مثلاً در همین سرویس سبد خرید زمانی که کاربر کد خودش را وارد می‌کند و دکمه ثبت کد را می‌زند همان لحظه باید نتیجه را ببیند و نمی‌توانیم آن را منتظر بگذاریم که کدی که وارد کرده معتبر است یا نه در چنین جاهایی ما مجبوریم با همان sync درخواست را بفرستیم و Request را بگیریم و به کاربر نمایش بدهیم .Asyn یا Asynchronous :در این روش سرویس مبدأ منتظر پاسخ سرویس مقصد نمی‌ماند و به کار خودش ادامه می‌دهد و بعد پاسخ برای آن ارسال می‌شود و ما برای پیاده‌سازی روش Asynchronous می‌توانیم از این سه روش زیر که مهم‌ترین روش‌ها هستند استفاده کنیم:HttpWebhookMessagebrockerHttp: در این روش ما می‌توانیم به‌جای پاسخ 200 پاسخ 202 به درخواست‌کننده بدهیم، و کد 202 به این معنی است که درخواست شما تحویل گرفته شده ولی هنوز در حال پردازش است و می‌توانیم با آن کد یک شناسه نیز به درخواست‌کننده ارسال کنیم که سرویس سبد خرید در بازه‌های زمانی مشخص چک کند که سرویس فرستنده کارش تمام شده است یا نه مانند شکل زیر:و این نیز یک نوع ارتباط Asynchronous که سرویس سبد خرید می‌تواند خیلی سریع Request 202 را بگیرد و به کارش ادامه دهد.Webhook: در این روش مثلاً سرویس سبد خرید یک API از سرویس سفارشی call می‌کند و یک URL هم به سرویس سفارش می‌دهد و می‌گوید زمانی که کارت تمام شد و سفارش را انجام دادی اطلاعات رو به این URL ارسال کن، و خود سرویس سفارش یک URL و یا API از سرویس سبد خرید را call می‌کند که دیتای موردنظر را برای آن ارسال می‌کند که این هم یک روش از پیاده‌سازی ارتباط Asynchronous است که می‌توانیم از این هم استفاده کنیمMessagebrocker: و اما روش آخر و محبوب‌ترین روش، استفاده از Messagebrockerها یا Eventbus است که در این روش ما یک Eventbus داریم. با یک پل ارتباطی داریم، و تمامی سرویس‌های ما سرویس‌هایی که نیاز دارند به ارتباط یک conection به این Eventbus دارند و هر سرویس که نیاز داشته باشد یک پیغام به سرویس دیگری ارسال کند. آن پیغام را به Eventbus ارسال می‌کند. مانند شکل زیر:EventbusEventbus آن پیغام را به سرویس موردنظر ارسال می‌کند که مزایای خیلی زیادی دارد. در مقاله Messagebrocker چیست بیشتر با این روش آشنا شوید. یکی از مهم‌ترین مزیت‌های این روش این است که اگر مثلاً سرویس سبد خرید بخواهد یک سفارش ثبت کند، پیغام خودش را که همان ثبت سفارش است ارسال می‌کند روی Eventbus وقتی که Eventbus می‌خواهد پیغام را به سرویس سفارش بفرستند می‌بیند که سرویس سفارش به هر دلیلی Run نیست، در این حالت پیغام در Eventbus می‌ماند و هر زمانی که سرویس سفارش‌ها Run بشود این پیغام را برای آن ارسال می‌کند، و یکی دیگر از مزیت‌های آن این است که اگر ما بخواهیم یک سرویس را scale کنیم به دلیل اینکه درخواست‌های یک سفارش زیاد شده است به‌راحتی می‌توانیم چند نمونه دیگر از آن سرویس را Run کنیم و هرکدام به Eventbus گوش بدهند و پیغام‌های موردنیاز را بردارند، پس ما نباید تمامی ارتباط بین سرویس‌ها و یا ارتباط بین لایهٔ UI با سرویس‌ها را به‌صورت sync یا مستقیم برقرار کنیم مانند شکل زیر:syncچون در این صورت تمامی قسمت‌های سیستم به یکدیگر وابسته هستند و بسیاری از مزایای معماری میکرو سرویس را از دست می‌دهیم.در معماری میکروسرویس بهتر است سرویس‌های ما که می‌خواهند با هم ارتباط برقرار کنند. با استفاده از Eventbus و یا همان RabbitMQ یا ابزارهای دیگری که وجود دارد ارتباطشان را برقرار کنند.مگر در مواقعی که مجبور باشیم از sync استفاده کنیم.و همچنین FrontEnd هم نباید به‌صورت مستقیم با میکروسرویس‌ها در ارتباط باشد و ما باید یک‌لایه اضافه کنیم که به این لایه Apigetway گفته می‌شود که FrontEnd ما با Apigetway ارتباط برقرار می‌کند برای دریافت داده‌ها Apigetway در خواست FrontEnd را می‌گیرد و بین میکرو سرویس‌هایی که موردنیاز است ارسال می‌کند و Response را جمع‌آوری می‌کند و برای FrontEnd ارسال می‌کند که بهتر است ارتباطات کلی ما در معماری میکروسرویس مانند شکل زیر باشد: