همانطور که قبلا توضیح داده شد، هنگامی که از ارتباطات مبتنی بر رویداد استفاده می کنید، یک میکروسرویس زمانی که اتفاق قابل توجهی رخ می دهد، مانند زمانی که یک نهاد تجاری را به روز می کند، رویدادی را منتشر می کند. سایر ریزسرویسها مشترک آن رویدادها هستند. هنگامی که یک میکروسرویس رویدادی را دریافت می کند، می تواند نهادهای تجاری خود را به روز کند، که ممکن است منجر به انتشار رویدادهای بیشتری شود. این جوهر مفهوم سازگاری نهایی است. این سیستم انتشار/اشتراک معمولاً با استفاده از پیادهسازی گذرگاه رویداد انجام میشود. اتوبوس رویداد را می توان به عنوان یک رابط با API مورد نیاز برای اشتراک و لغو اشتراک رویدادها و انتشار رویدادها طراحی کرد. همچنین میتواند یک یا چند پیادهسازی بر اساس هر ارتباط بین فرآیندی یا پیامرسانی، مانند صف پیامرسانی یا گذرگاه خدماتی که از ارتباط ناهمزمان و مدل انتشار/اشتراک پشتیبانی میکند، داشته باشد.
میتوانید از رویدادها برای پیادهسازی تراکنشهای تجاری که چندین سرویس را در بر میگیرند، استفاده کنید، که به شما یکپارچگی نهایی بین آن خدمات را میدهد. یک تراکنش در نهایت سازگار شامل یک سری اقدامات توزیع شده است. در هر اقدام، میکروسرویس یک نهاد تجاری را به روز می کند و رویدادی را منتشر می کند که اقدام بعدی را آغاز می کند.
این بخش توضیح می دهد که چگونه می توانید این نوع ارتباط را با دات نت با استفاده از یک رابط گذرگاه رویداد عمومی پیاده سازی کنید. چندین پیاده سازی بالقوه وجود دارد که هر کدام از فناوری یا زیرساخت متفاوتی مانند RabbitMQ، Azure Service Bus یا هر گذرگاه خدمات تجاری منبع باز یا شخص ثالث دیگری استفاده می کنند.
همانطور که در بخش معماری اشاره شد، میتوانید از میان چندین فناوری پیامرسانی برای پیادهسازی گذرگاه رویداد انتزاعی خود انتخاب کنید. اما این فناوری ها در سطوح مختلفی قرار دارند. به عنوان مثال، RabbitMQ، یک واسطه انتقال پیام، در سطح پایین تری نسبت به محصولات تجاری مانند Azure Service Bus، NServiceBus، MassTransit یا Brighter قرار دارد. اکثر این محصولات میتوانند در بالای RabbitMQ یا Azure Service Bus کار کنند. انتخاب محصول شما به چند ویژگی و میزان مقیاس پذیری خارج از جعبه برای برنامه خود بستگی دارد.
مانند نمونه eShopOnContainers، برای پیادهسازی یک گذرگاه رویداد اثبات مفهوم برای محیط توسعهتان، یک پیادهسازی ساده در بالای RabbitMQ که بهعنوان یک کانتینر اجرا میشود، ممکن است کافی باشد. اما برای سیستمهای تولیدی و حیاتی که نیاز به مقیاسپذیری بالایی دارند، ممکن است بخواهید Azure Service Bus را ارزیابی کرده و از آن استفاده کنید.
اگر به انتزاعهای سطح بالا و ویژگیهای غنیتر مانند Sagas برای فرآیندهای طولانیمدت نیاز دارید که توسعه توزیعشده را آسانتر میکنند، سایر اتوبوسهای خدمات تجاری و منبع باز مانند NServiceBus، MassTransit و Brighter ارزش ارزیابی دارند. در این مورد، انتزاعها و APIهای مورد استفاده معمولاً مستقیماً همانهایی هستند که بهجای انتزاعهای خود شما توسط اتوبوسهای خدمات سطح بالا ارائه میشوند (مانند انتزاعهای اتوبوس رویداد ساده ارائهشده در eShopOnContainers). برای این موضوع، می توانید با استفاده از NServiceBus (نمونه مشتق شده اضافی که توسط نرم افزار خاص پیاده سازی شده است) در مورد eShopOnContainers فورک شده تحقیق کنید.
البته، همیشه میتوانید ویژگیهای گذرگاه خدمات خود را بر روی فناوریهای سطح پایینتر مانند RabbitMQ و Docker ایجاد کنید، اما کار مورد نیاز برای «اختراع مجدد چرخ» ممکن است برای یک برنامه سازمانی سفارشی بسیار پرهزینه باشد.
تکرار: انتزاعها و پیادهسازی گذرگاه رویداد نمونه که در نمونه eShopOnContainers به نمایش گذاشته شدهاند، صرفاً بهعنوان اثبات مفهوم مورد استفاده قرار میگیرند. هنگامی که تصمیم گرفتید که می خواهید ارتباط ناهمزمان و رویداد محور داشته باشید، همانطور که در بخش فعلی توضیح داده شد، باید محصول اتوبوس خدماتی را انتخاب کنید که به بهترین وجه با نیازهای شما برای تولید مطابقت دارد.
رویدادهای یکپارچه سازی برای همگام سازی حالت دامنه در چندین میکروسرویس یا سیستم های خارجی استفاده می شود. این عملکرد با انتشار رویدادهای یکپارچه سازی خارج از میکروسرویس انجام می شود. هنگامی که یک رویداد برای میکروسرویسهای گیرنده چندگانه منتشر میشود (به تعداد میکروسرویسهایی که در رویداد یکپارچهسازی مشترک شدهاند)، کنترلکننده رویداد مناسب در هر میکروسرویس گیرنده، رویداد را مدیریت میکند.
یک رویداد یکپارچه سازی اساساً یک کلاس نگهدارنده داده است، مانند مثال زیر:
public class ProductPriceChangedIntegrationEvent : IntegrationEvent
{
public int ProductId { get; private set; }
public decimal NewPrice { get; private set; }
public decimal OldPrice { get; private set; }
public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice,
decimal oldPrice)
{
ProductId = productId;
NewPrice = newPrice;
OldPrice = oldPrice;
}
}
رویدادهای یکپارچهسازی را میتوان در سطح کاربرد هر میکروسرویس تعریف کرد، بنابراین آنها از سایر ریزسرویسها جدا میشوند، به نحوی که قابل مقایسه با نحوه تعریف ViewModels در سرور و مشتری است. آنچه توصیه نمی شود اشتراک گذاری یک کتابخانه رویدادهای یکپارچه سازی مشترک در چندین میکروسرویس است. انجام این کار می تواند آن میکروسرویس ها را با یک کتابخانه داده با تعریف رویداد واحد پیوند دهد. شما نمی خواهید این کار را به همان دلایلی انجام دهید که نمی خواهید یک مدل دامنه مشترک را بین چندین میکروسرویس به اشتراک بگذارید: میکروسرویس ها باید کاملاً مستقل باشند. برای اطلاعات بیشتر، این پست وبلاگ را در مورد میزان داده هایی که باید در رویدادها قرار دهید، ببینید.
فقط چند نوع کتابخانه وجود دارد که باید در میان میکروسرویس ها به اشتراک بگذارید. یکی کتابخانه هایی هستند که بلوک های برنامه نهایی هستند، مانند Event Bus مشتری API، مانند eShopOnContainers. دیگری کتابخانههایی است که ابزارهایی را تشکیل میدهند که میتوانند بهعنوان اجزای NuGet به اشتراک گذاشته شوند، مانند سریالسازهای JSON.
یک گذرگاه رویداد اجازه می دهد تا ارتباطی به سبک انتشار/اشتراک بین میکروسرویس ها بدون نیاز به آگاهی صریح اجزا از یکدیگر وجود داشته باشد.
در الگوی Observer، شی اصلی شما (معروف به Observable) سایر اشیاء علاقه مند (معروف به Observers) را با اطلاعات مرتبط (رویدادها) مطلع می کند.
هدف از الگوی Publish/Subscribe همانند الگوی Observer است: میخواهید در صورت وقوع رویدادهای خاصی به سایر سرویسها اطلاع دهید. اما تفاوت مهمی بین الگوهای Observer و Pub/Sub وجود دارد. در الگوی مشاهده گر، پخش مستقیماً از مشاهده پذیر به ناظران انجام می شود، بنابراین آنها یکدیگر را می شناسند. اما هنگام استفاده از الگوی Pub/Sub، جزء سومی به نام بروکر یا واسطه پیام یا اتوبوس رویداد وجود دارد که هم توسط ناشر و هم مشترک شناخته می شود. بنابراین، هنگام استفاده از الگوی Pub/Sub، ناشر و مشترکین دقیقاً به لطف اتوبوس رویداد یا کارگزار پیام ذکر شده جدا می شوند.
چگونه بین ناشر و مشترک به ناشناس بودن می رسید؟ یک راه آسان این است که اجازه دهید یک واسطه تمام ارتباطات را انجام دهد. اتوبوس رویداد یکی از این واسطه هاست.
اتوبوس رویداد معمولاً از دو بخش تشکیل شده است:
خوب است که گذرگاه رویداد از طریق یک رابط تعریف شود تا بتوان آن را با چندین فناوری مانند RabbitMQ، Azure Service bus یا موارد دیگر پیادهسازی کرد. با این حال، و همانطور که قبلا ذکر شد، استفاده از انتزاعهای خود (رابط اتوبوس رویداد) تنها در صورتی خوب است که به ویژگیهای گذرگاه رویداد اصلی که توسط انتزاعهایتان پشتیبانی میشوند، نیاز داشته باشید. اگر به ویژگیهای گذرگاه خدمات غنیتری نیاز دارید، احتمالاً باید از API و انتزاعهای ارائهشده توسط اتوبوس خدمات تجاری مورد علاقهتان به جای انتزاعهای خود استفاده کنید.
بیایید با برخی از کدهای پیاده سازی برای رابط اتوبوس رویداد و پیاده سازی های ممکن برای اهداف اکتشافی شروع کنیم. رابط باید عمومی و ساده باشد، مانند رابط زیر.
public interface IEventBus
{
void Publish(IntegrationEvent @event);
void Subscribe<T, TH>()
where T : IntegrationEvent
where TH : IIntegrationEventHandler<T>;
void SubscribeDynamic<TH>(string eventName)
where TH : IDynamicIntegrationEventHandler;
void UnsubscribeDynamic<TH>(string eventName)
where TH : IDynamicIntegrationEventHandler;
void Unsubscribe<T, TH>()
where TH : IIntegrationEventHandler<T>
where T : IntegrationEvent;
}
روش انتشار ساده است. گذرگاه رویداد رویداد یکپارچهسازی ارسال شده به آن را برای هر میکروسرویس یا حتی یک برنامه خارجی مشترک در آن رویداد پخش میکند. این روش توسط میکروسرویسی که رویداد را منتشر می کند استفاده می شود.
روش های Subscribe (بسته به آرگومان ها می توانید چندین پیاده سازی داشته باشید) توسط میکروسرویس هایی که می خواهند رویدادها را دریافت کنند استفاده می شود. این روش دو آرگومان دارد. اولین رویداد یکپارچه سازی برای اشتراک در (IntegrationEvent) است. آرگومان دوم، کنترلکننده رویداد یکپارچهسازی (یا روش برگشت به تماس)، با نام IIntegrationEventHandler<T> است که زمانی اجرا میشود که میکروسرویس گیرنده پیام رویداد یکپارچهسازی را دریافت کند.