Beberapa aturan tentang cara mengatur titik, antrian, dan cara memberi nama dengan benar agar nyaman.
| exchange | type | binding_queue | binding_key | |-------------------------------------------------------| | user.write | topic | user.created.app2 | user.created |
KonsepAMQP (Advanced Message Queuing Protocol) adalah protokol terbuka untuk mentransfer pesan antar komponen sistem.
Penyedia (Penerbit / Produser) - program yang mengirim pesan.
Pelanggan (Konsumen) - program yang menerima pesan. Biasanya, pelanggan dalam keadaan menunggu pesan.
Antrian - Antrian pesan.
Exchange Point (Exchange) - Titik awal pertukaran antrian, yang berkaitan dengan perutean.
Aturan 1
Setiap antrian harus mewakili hanya satu jenis pekerjaan. Jangan mencampur berbagai jenis pesan dalam antrian yang sama. Dan ketika aturan ini dihormati, kami dapat dengan jelas memberi nama antrian tugas yang disajikan kepada mereka.
Aturan 2
Hindari mengirim ulang pesan ke antrian. Jika Anda menemukan bahwa pelanggan Anda mencoba mengirim ulang pesan apa pun ke antrian lain tanpa pemrosesan nyata, kemungkinan besar ada sesuatu yang tidak dirancang dengan benar. Routing adalah tanggung jawab pertukaran poin, bukan antrian.
Aturan 3
Pemasok tidak perlu tahu apa pun tentang antrian. Salah satu ide utama AMQP adalah pembagian tanggung jawab antara titik dan antrian, sehingga pemasok tidak perlu khawatir tentang menyampaikan pesan kepada pelanggan.
Contoh dan solusi
Misalkan Anda ingin merancang poin dan antrian untuk acara rekaman terkait "kustom". Acara perekaman akan dipecat dalam satu aplikasi atau lebih, dan pesan-pesan ini akan digunakan oleh beberapa aplikasi lain.
| object | event | |------------------| | user | created | | user | updated | | user | deleted |
Pertanyaan pertama yang biasanya ditanyakan adalah berbagai peristiwa dari satu objek (objek "pengguna" dalam contoh ini), haruskah satu titik pertukaran digunakan untuk mempublikasikan ketiga peristiwa, atau haruskah 3 titik terpisah digunakan untuk setiap peristiwa? Atau, singkatnya, satu titik pertukaran, atau banyak?
Sebelum menjawab pertanyaan ini, saya ingin bertanya pertanyaan lain: apakah kita benar-benar memerlukan poin terpisah untuk kasus ini? Bagaimana jika kita abstrak semua 3 jenis peristiwa sebagai peristiwa "tulis" yang subtipenya "dibuat", "diperbarui" dan "dihapus"?
| object | event | sub-type | |-----------------------------| | user | write | created | | user | write | updated | | user | write | deleted |
Solusi 1
Solusi paling sederhana adalah membuat antrian βuser.writeβ, dan mempublikasikan semua pesan dari peristiwa rekaman pengguna ke antrian ini melalui titik pertukaran global.
Keputusan 2
Solusi paling sederhana tidak dapat berfungsi ketika ada aplikasi kedua (memiliki logika pemrosesan yang berbeda) yang ingin berlangganan pesan apa pun yang diterbitkan dalam antrian. Ketika beberapa aplikasi ditandatangani, setidaknya kita perlu satu titik dengan tipe "fanout" dengan binding ke beberapa antrian. Dengan demikian, pesan dikirim ke titik, dan itu menduplikasi pesan di setiap antrian. Setiap antrian mewakili pekerjaan pemrosesan untuk setiap aplikasi.
| queue | subscriber | |-------------------------------| | user.write.app1 | app1 | | user.write.app2 | app2 | | exchange | type | binding_queue | |---------------------------------------| | user.write | fanout | user.write.app1 | | user.write | fanout | user.write.app2 |
Solusi kedua berfungsi dengan baik jika setiap pelanggan benar-benar ingin menangani semua subtipe acara "user.write". Misalnya, jika aplikasi pelanggan dirancang untuk hanya menyimpan log transaksi.
Di sisi lain, itu tidak terlalu baik ketika beberapa pelanggan berada di luar organisasi Anda dan Anda ingin memberi tahu mereka hanya tentang peristiwa spesifik tertentu, misalnya, app2 harus menerima pesan tentang pembuatan pengguna dan tidak boleh tahu tentang memperbarui dan menghapus acara.
Keputusan 3
Untuk mengatasi masalah di atas, kita harus mengekstrak acara "user.created" dari jenis "user.write". Pertukaran poin dengan jenis topik dapat membantu kami. Saat menerbitkan pesan, kita akan menggunakan user.created / user.updated / user.deleted sebagai kunci routing pada suatu titik, sehingga kita dapat menempatkan kunci komunikasi "user. *" Dalam antrian "user.write.app1" dan kunci komunikasi "user.created" dalam antrian "user.created.app2".
| queue | subscriber | |---------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | exchange | type | binding_queue | binding_key | |-------------------------------------------------------| | user.write | topic | user.write.app1 | user.* | | user.write | topic | user.created.app2 | user.created |
Keputusan 4
Jenis topik topik titik pertukaran lebih fleksibel jika berpotensi lebih banyak jenis acara. Tetapi jika Anda mengetahui dengan jelas jumlah kejadian, Anda juga dapat menggunakan jenis "langsung" untuk meningkatkan kinerja.
| queue | subscriber | |---------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | exchange | type | binding_queue | binding_key | |--------------------------------------------------------| | user.write | direct | user.write.app1 | user.created | | user.write | direct | user.write.app1 | user.updated | | user.write | direct | user.write.app1 | user.deleted | | user.write | direct | user.created.app2 | user.created |
Kami kembali ke pertanyaan "satu poin, atau banyak?". Selama semua solusi hanya menggunakan satu titik, itu berfungsi dengan baik, tidak ada yang buruk. Dalam situasi apa kita dapat memerlukan beberapa poin?
Keputusan 5
Mari kita lihat contoh ketika, di samping peristiwa yang dibuat, diperbarui, dan dihapus yang dijelaskan di atas, kita memiliki kelompok peristiwa lain: input dan output - sekelompok peristiwa yang menggambarkan "perilaku pengguna" daripada "rekaman data". Untuk kelompok acara yang berbeda, strategi perutean dan kesepakatan yang sama sekali berbeda pada kunci dan nama antrian mungkin diperlukan, dan untuk ini, titik pertukaran yang terpisah diperlukan.
| queue | subscriber | |----------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | user.behavior.app3 | app3 | | exchange | type | binding_queue | binding_key | |--------------------------------------------------------------| | user.write | topic | user.write.app1 | user.* | | user.write | topic | user.created.app2 | user.created | | user.behavior | topic | user.behavior.app3 | user.* |
Terjemahan gratis dari artikel
RabbitMQ Exchange dan Desain Antrian Trade-off .