Bagikan melalui


Menerapkan bus peristiwa dengan RabbitMQ untuk lingkungan pengembangan atau pengujian

Tip

Konten ini adalah kutipan dari eBook, .NET Microservices Architecture for Containerized .NET Applications, tersedia di .NET Docs atau sebagai PDF yang dapat diunduh gratis dan dapat dibaca secara offline.

Arsitektur Layanan Mikro .NET untuk thumbnail sampul eBook Aplikasi .NET Dalam Kontainer.

Kita harus mulai dengan mengatakan bahwa jika Anda membuat bus peristiwa kustom berdasarkan RabbitMQ yang berjalan dalam kontainer, seperti yang dilakukan aplikasi eShopOnContainers, itu harus digunakan hanya untuk lingkungan pengembangan dan pengujian Anda. Jangan gunakan untuk lingkungan produksi Anda, kecuali Anda membangunnya sebagai bagian dari bus layanan siap produksi seperti yang dijelaskan di bagian Sumber daya tambahan di bawah ini. Bus peristiwa kustom sederhana mungkin kehilangan banyak fitur penting siap produksi yang dimiliki bus layanan komersial.

Salah satu implementasi kustom bus peristiwa di eShopOnContainers pada dasarnya adalah pustaka menggunakan RabbitMQ API. (Ada implementasi lain berdasarkan Azure Service Bus.)

Implementasi bus peristiwa dengan RabbitMQ memungkinkan layanan mikro berlangganan peristiwa, menerbitkan peristiwa, dan menerima peristiwa, seperti yang ditunjukkan pada Gambar 6-21.

Diagram memperlihatkan RabbitMQ antara pengirim pesan dan penerima pesan.

Gambar 6-21. Implementasi RabbitMQ dari bus peristiwa

RabbitMQ berfungsi sebagai perantara antara penerbit pesan dan pelanggan, untuk menangani distribusi. Dalam kode, kelas EventBusRabbitMQ mengimplementasikan antarmuka IEventBus generik. Implementasi ini didasarkan pada Injeksi Dependensi sehingga Anda dapat menukar dari versi dev/test ini ke versi produksi.

public class EventBusRabbitMQ : IEventBus, IDisposable
{
    // Implementation using RabbitMQ API
    //...
}

Implementasi RabbitMQ dari sampel dev/test event bus adalah kode boilerplate. Ini harus menangani koneksi ke server RabbitMQ dan menyediakan kode untuk menerbitkan peristiwa pesan ke antrean. Ini juga harus menerapkan kamus koleksi penanganan aktivitas integrasi untuk setiap jenis peristiwa; jenis peristiwa ini dapat memiliki instansiasi yang berbeda dan langganan yang berbeda untuk setiap layanan mikro penerima, seperti yang ditunjukkan pada Gambar 6-21.

Menerapkan metode publikasi sederhana dengan RabbitMQ

Kode berikut adalah versi yang disederhanakan dari implementasi bus peristiwa untuk RabbitMQ, untuk menampilkan seluruh skenario. Anda tidak benar-benar menangani koneksi dengan cara ini. Untuk melihat implementasi lengkap, lihat kode aktual di repositori 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);
       }
    }
}

Kode aktual metode Publish di aplikasi eShopOnContainers ditingkatkan dengan menggunakan kebijakan coba lagi Polly, yang mencoba kembali tugas beberapa kali jika kontainer RabbitMQ belum siap. Skenario ini dapat terjadi ketika docker-compose memulai kontainer; misalnya, kontainer RabbitMQ mungkin dimulai lebih lambat daripada kontainer lainnya.

Seperti disebutkan sebelumnya, ada banyak kemungkinan konfigurasi di RabbitMQ, sehingga kode ini harus digunakan hanya untuk lingkungan dev/test.

Menerapkan kode langganan dengan RabbitMQ API

Seperti halnya kode penerbitan, kode berikut adalah penyederhanaan bagian dari implementasi bus peristiwa untuk RabbitMQ. Sekali lagi, Anda biasanya tidak perlu mengubahnya kecuali Anda meningkatkannya.

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>();
    }
}

Setiap jenis peristiwa memiliki saluran terkait untuk mendapatkan peristiwa dari RabbitMQ. Anda kemudian dapat memiliki penanganan aktivitas sebanyak yang diperlukan per saluran dan jenis peristiwa.

Metode Berlangganan menerima objek IIntegrationEventHandler, yang seperti metode panggilan balik dalam layanan mikro saat ini, ditambah objek IntegrationEvent terkait. Kode kemudian menambahkan penanganan aktivitas tersebut ke daftar penanganan aktivitas yang dapat dimiliki setiap jenis peristiwa integrasi per layanan mikro klien. Jika kode klien belum berlangganan peristiwa, kode membuat saluran untuk jenis peristiwa sehingga dapat menerima peristiwa dalam gaya dorong dari RabbitMQ ketika peristiwa tersebut diterbitkan dari layanan lain.

Seperti disebutkan di atas, bus peristiwa yang diterapkan di eShopOnContainers hanya memiliki tujuan pendidikan, karena hanya menangani skenario utama, sehingga tidak siap untuk produksi.

Untuk skenario produksi, periksa sumber daya tambahan di bawah ini, khusus untuk RabbitMQ, dan bagian Menerapkan komunikasi berbasis peristiwa antara layanan mikro.

Sumber Daya Tambahan:

Solusi siap produksi dengan dukungan untuk RabbitMQ.