e باید با گفتن این که اگر گذرگاه رویداد سفارشی خود را بر اساس RabbitMQ در حال اجرا در یک کانتینر ایجاد کنید، همانطور که برنامه eShopOnContainers انجام می دهد، باید فقط برای محیط های توسعه و آزمایش خود استفاده شود. از آن برای محیط تولید خود استفاده نکنید، مگر اینکه آن را به عنوان بخشی از اتوبوس خدمات آماده تولید بسازید، همانطور که در بخش منابع اضافی در زیر توضیح داده شده است. یک اتوبوس رویداد سفارشی ساده ممکن است بسیاری از ویژگیهای حیاتی آماده تولید را که یک اتوبوس خدمات تجاری دارد، نداشته باشد.
یکی از پیاده سازی های سفارشی گذرگاه رویداد در eShopOnContainers اساساً یک کتابخانه با استفاده از RabbitMQ API است. (یک پیاده سازی دیگر بر اساس Azure Service Bus وجود دارد.)
پیاده سازی گذرگاه رویداد با RabbitMQ به میکروسرویس ها اجازه می دهد تا در رویدادها مشترک شوند، رویدادها را منتشر کنند و رویدادها را دریافت کنند، همانطور که در شکل 6-21 نشان داده شده است.
RabbitMQ به عنوان یک واسطه بین ناشر پیام و مشترکین برای مدیریت توزیع عمل می کند. در کد، کلاس EventBusRabbitMQ رابط عمومی IEventBus را پیاده سازی می کند. این پیاده سازی مبتنی بر Dependency Injection است تا بتوانید از این نسخه توسعه دهنده/تست به نسخه تولیدی مبادله کنید.
public class EventBusRabbitMQ : IEventBus, IDisposable
{
// Implementation using RabbitMQ API
//...
}
پیادهسازی RabbitMQ یک گذرگاه رویداد برنامهنویس/تست نمونه، کد boilerplate است. باید اتصال به سرور RabbitMQ را مدیریت کند و کدی را برای انتشار یک رویداد پیام در صف ها ارائه کند. همچنین باید فرهنگ لغت مجموعهای از مدیریتکنندههای رویداد یکپارچهسازی را برای هر نوع رویداد پیادهسازی کند. این نوع رویدادها می توانند برای هر میکروسرویس گیرنده یک نمونه متفاوت و اشتراک های متفاوت داشته باشند.
کد زیر یک نسخه ساده شده از پیاده سازی گذرگاه رویداد برای RabbitMQ است تا کل سناریو را به نمایش بگذارد. شما واقعاً ارتباط را اینگونه مدیریت نمی کنید. برای مشاهده اجرای کامل، کد واقعی را در مخزن dotnet-architecture/eShopOnContainers ببینید.
public class EventBusRabbitMQ : IEventBus, IDisposable
{
// Member objects and other methods ...
// ...
public void Publish(IntegrationEvent @event)
{
var eventName = @event.GetType().Name;
var factory = new ConnectionFactory() { HostName = _connectionString };
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: _brokerName,
type: "direct");
string message = JsonConvert.SerializeObject(@event);
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: _brokerName,
routingKey: eventName,
basicProperties: null,
body: body);
}
}
}
کد واقعی روش Publish در برنامه eShopOnContainers با استفاده از یک خط مشی امتحان مجدد Polly بهبود می یابد، که در صورت آماده نبودن ظرف RabbitMQ، این کار را چند بار تکرار می کند. این سناریو می تواند زمانی رخ دهد که docker-compose در حال راه اندازی کانتینرها است. برای مثال، محفظه RabbitMQ ممکن است کندتر از سایر کانتینرها شروع به کار کند.
همانطور که قبلا ذکر شد، تنظیمات احتمالی زیادی در RabbitMQ وجود دارد، بنابراین این کد باید فقط برای محیطهای dev/test استفاده شود.
همانند کد انتشار، کد زیر سادهسازی بخشی از اجرای اتوبوس رویداد برای RabbitMQ است. باز هم، معمولاً نیازی به تغییر آن ندارید، مگر اینکه در حال بهبود آن باشید.
public class EventBusRabbitMQ : IEventBus, IDisposable
{
// Member objects and other methods ...
// ...
public void Subscribe<T, TH>()
where T : IntegrationEvent
where TH : IIntegrationEventHandler<T>
{
var eventName = _subsManager.GetEventKey<T>();
var containsKey = _subsManager.HasSubscriptionsForEvent(eventName);
if (!containsKey)
{
if (!_persistentConnection.IsConnected)
{
_persistentConnection.TryConnect();
}
using (var channel = _persistentConnection.CreateModel())
{
channel.QueueBind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
}
}
_subsManager.AddSubscription<T, TH>();
}
}
هر نوع رویداد یک کانال مرتبط برای دریافت رویدادها از RabbitMQ دارد. سپس می توانید به تعداد مورد نیاز در هر کانال و نوع رویداد، کنترل کننده رویداد داشته باشید.
متد Subscribe یک شی IIntegrationEventHandler را میپذیرد، که مانند یک روش بازگشت به تماس در میکروسرویس فعلی است، به علاوه شی IntegrationEvent مربوط به آن. سپس کد آن رویداد کنترلکننده را به فهرست کنترلکنندههای رویداد اضافه میکند که هر نوع رویداد یکپارچهسازی میتواند در هر میکروسرویس مشتری داشته باشد. اگر کد مشتری قبلاً در رویداد مشترک نشده باشد، کد یک کانال برای نوع رویداد ایجاد می کند تا بتواند رویدادها را به سبک فشاری از RabbitMQ دریافت کند، زمانی که آن رویداد از هر سرویس دیگری منتشر می شود.
همانطور که در بالا ذکر شد، اتوبوس رویداد پیادهسازی شده در eShopOnContainers فقط یک هدف آموزشی دارد، زیرا تنها سناریوهای اصلی را کنترل میکند، بنابراین برای تولید آماده نیست.