RabbitMQ dan hubungan antara saluran dan koneksi

176

The klien RabbitMQ Java memiliki konsep berikut:

  • Connection - koneksi ke instance server RabbitMQ
  • Channel - ???
  • Kumpulan utas konsumen - kumpulan utas yang mengkonsumsi pesan dari antrian server RabbitMQ
  • Antrian - struktur yang menyimpan pesan dalam urutan FIFO

Saya mencoba memahami hubungan, dan yang lebih penting , hubungan di antara mereka.

  1. Saya masih tidak yakin apa Channelitu, selain fakta bahwa ini adalah struktur yang Anda terbitkan dan konsumsi, dan bahwa itu dibuat dari koneksi terbuka. Jika seseorang dapat menjelaskan kepada saya apa yang dilambangkan oleh "Saluran", ini mungkin membantu membersihkan beberapa hal.
  2. Apa hubungan antara Saluran dan Antrean? Dapatkah Saluran yang sama digunakan untuk berkomunikasi ke Antrian yang berlipat ganda, atau apakah harus 1: 1?
  3. Apa hubungan antara Antrian dan Kelompok Konsumen? Bisakah beberapa Konsumen berlangganan Antrian yang sama? Apakah beberapa Antrian dapat dikonsumsi oleh Konsumen yang sama? Atau apakah hubungannya 1: 1?

Terima kasih sebelumnya atas bantuan apa pun di sini!


sumber
Jawaban atas pertanyaan ini membuat saya melaporkan masalah ini dengan klien golang daripada mengajukan pertanyaan di sini.
Bruce Adams
Saluran adalah konsep logis yang digunakan untuk multiplex koneksi TCP fisik tunggal antara klien dan sebuah node. Nomor saluran termasuk dalam header pesan dari bingkai AMQP.
ymas

Jawaban:

196
  1. A Connectionmewakili koneksi TCP nyata ke broker pesan, sedangkan a Channeladalah koneksi virtual (koneksi AMQP) di dalamnya. Dengan cara ini Anda dapat menggunakan koneksi (virtual) sebanyak yang Anda inginkan di dalam aplikasi Anda tanpa membebani broker dengan koneksi TCP.

  2. Anda dapat menggunakannya Channeluntuk semuanya. Namun, jika Anda memiliki beberapa utas, disarankan untuk menggunakan Channelutas yang berbeda untuk setiap utas.

    Keamanan utas saluran di Panduan API Klien Java :

    Mesin virtual saluran aman untuk digunakan oleh banyak utas. Permintaan ke Saluran diserialisasi, dengan hanya satu utas yang dapat menjalankan perintah pada Saluran sekaligus. Meski begitu, aplikasi harus lebih memilih menggunakan Saluran per utas daripada berbagi Saluran yang sama di beberapa utas.

    Tidak ada hubungan langsung antara Channeldan Queue. A Channeldigunakan untuk mengirim perintah AMQP ke broker. Ini bisa berupa pembuatan antrian atau serupa, tetapi konsep-konsep ini tidak terikat bersama.

  3. Masing-masing Consumerberjalan di utasnya sendiri yang dialokasikan dari kumpulan utas konsumen. Jika banyak Konsumen berlangganan Antrian yang sama, broker menggunakan round-robin untuk mendistribusikan pesan di antara mereka secara merata. Lihat Tutorial dua: "Antrian Kerja" .

    Dimungkinkan juga untuk melampirkan yang sama Consumerke beberapa Antrian. Anda dapat memahami Konsumen sebagai panggilan balik. Ini disebut setiap kali pesan tiba di Antrian yang terikat dengan Konsumen. Untuk kasus Klien Java, setiap Konsumen memiliki metode handleDelivery(...), yang mewakili metode panggilan balik. Apa yang biasanya Anda lakukan adalah, subclass DefaultConsumerdan override handleDelivery(...). Catatan: Jika Anda melampirkan instance Konsumen yang sama ke beberapa antrian, metode ini akan dipanggil oleh utas berbeda. Jadi, selaraskan sinkronisasi jika perlu.

Bengt
sumber
4
Hanya untuk menambah dari dokumentasi: Callback ke Konsumen dikirim pada utas yang terpisah dari utas yang dikelola oleh Koneksi. Ini berarti bahwa Konsumen dapat dengan aman memanggil metode pemblokiran pada Connection atau Channel, seperti queueDeclare, txCommit, basicCancel atau basicPublish. Setiap Saluran memiliki utas pengirimannya sendiri. Untuk kasus penggunaan paling umum dari satu Konsumen per Saluran, ini berarti Konsumen tidak memegang Konsumen lain. Jika Anda memiliki beberapa Konsumen per Saluran, ketahuilah bahwa Pelanggan yang sudah lama berjalan dapat menahan pengiriman panggilan balik ke Konsumen lain di Saluran itu.
filip
1
Jika Anda melampirkan instance Pelanggan yang sama ke beberapa Antrean dari Saluran yang sama, itu berarti bahwa callback dikirim pada utas yang sama. Dalam hal ini Anda tidak perlu sinkronisasi, bukan?
filip
Dapatkah saya menggunakan hanya satu koneksi dan menggunakan kumpulan saluran alih-alih kumpulan koneksi? Apakah ini akan memengaruhi throughput penerbitan pesan?
qeek
4
Saya pikir referensi ini ke Java Client API sekarang sudah ketinggalan zaman dan pada kenyataannya referensi hari ini secara langsung bertentangan dengan kutipan dalam jawaban ini. Referensi hari ini mengatakan "Mesin virtual saluran tidak boleh dibagi di antara utas".
Edwin Dalorzo
1
@ EdwinDalorzo - sepertinya siapa pun yang awalnya menulis dokumentasi tidak sepenuhnya memahami dikotomi saluran-koneksi. Arsitektur dasar AMQP 0.9.1 benar-benar memperlakukan saluran sebagai sesi, sehingga utas berbeda yang berbagi sesi benar-benar tidak masuk akal. Dugaan saya adalah alasan untuk perubahan itu.
theMayer
53

Pemahaman konseptual yang baik tentang apa yang protokol AMQP lakukan "di bawah tenda" berguna di sini. Saya akan menawarkan bahwa dokumentasi dan API yang AMQP 0.9.1 pilih untuk digunakan membuat ini sangat membingungkan, jadi pertanyaannya sendiri adalah salah satu yang harus dihadapi banyak orang.

TL; DR

Sebuah koneksi adalah fisik dinegosiasikan TCP socket dengan server AMQP. Klien yang diimplementasikan dengan benar akan memiliki salah satu dari ini per aplikasi, aman untuk benang, dapat digunakan di antara utas.

Sebuah saluran adalah sesi aplikasi tunggal pada sambungan. Utas akan memiliki satu atau lebih dari sesi ini. Arsitektur AMQP 0.9.1 adalah bahwa ini tidak untuk dibagikan di antara utas, dan harus ditutup / dihancurkan ketika utas yang membuatnya selesai dengannya. Mereka juga ditutup oleh server ketika berbagai pelanggaran protokol terjadi.

Sebuah konsumen adalah membangun virtual yang mewakili kehadiran "kotak" pada saluran tertentu. Penggunaan konsumen memberi tahu broker untuk mendorong pesan dari antrian tertentu ke titik akhir saluran itu.

Fakta Koneksi

Pertama, seperti yang orang lain tunjukkan dengan benar, koneksi adalah objek yang mewakili koneksi TCP yang sebenarnya ke server. Koneksi ditentukan pada tingkat protokol di AMQP, dan semua komunikasi dengan broker terjadi melalui satu atau lebih koneksi.

  • Karena ini adalah koneksi TCP yang sebenarnya, ia memiliki Alamat IP dan Port #.
  • Parameter protokol dinegosiasikan berdasarkan per-klien sebagai bagian dari pengaturan koneksi (proses yang dikenal sebagai jabat tangan) .
  • Ini dirancang untuk berumur panjang ; ada beberapa kasus di mana penutupan koneksi merupakan bagian dari desain protokol.
  • Dari perspektif OSI, itu mungkin berada di suatu tempat di sekitar Layer 6
  • Detak jantung dapat diatur untuk memantau status koneksi, karena TCP tidak mengandung apa pun untuk melakukan hal ini.
  • Yang terbaik adalah memiliki thread khusus mengelola membaca dan menulis ke soket TCP yang mendasarinya. Sebagian besar, jika tidak semua, klien RabbitMQ melakukan ini. Dalam hal itu, mereka umumnya aman-benang.
  • Secara relatif, koneksi adalah "mahal" untuk dibuat (karena jabat tangan), tetapi secara praktis, ini benar-benar tidak masalah. Sebagian besar proses hanya membutuhkan satu objek koneksi. Tetapi, Anda dapat mempertahankan koneksi dalam kumpulan, jika Anda menemukan Anda membutuhkan lebih banyak throughput daripada satu thread / socket dapat menyediakan (tidak mungkin dengan teknologi komputasi saat ini).

Fakta Saluran

Sebuah Saluran adalah sesi aplikasi yang dibuka untuk setiap bagian dari aplikasi Anda untuk berkomunikasi dengan broker RabbitMQ. Ini beroperasi melalui satu koneksi , dan mewakili sesi dengan broker.

  • Karena ini merupakan bagian logis dari logika aplikasi, setiap saluran biasanya ada di utasnya sendiri.
  • Biasanya, semua saluran yang dibuka oleh aplikasi Anda akan berbagi satu koneksi (itu adalah sesi ringan yang beroperasi di atas koneksi). Koneksi aman, jadi ini OK.
  • Sebagian besar operasi AMQP dilakukan melalui saluran.
  • Dari perspektif OSI Layer, saluran mungkin sekitar Layer 7 .
  • Saluran dirancang untuk bersifat sementara ; bagian dari desain AMQP adalah bahwa saluran biasanya ditutup sebagai respons terhadap kesalahan (misalnya, mendeklarasikan ulang antrian dengan parameter yang berbeda sebelum menghapus antrian yang ada).
  • Karena bersifat sementara, saluran tidak boleh digabungkan dengan aplikasi Anda.
  • Server menggunakan integer untuk mengidentifikasi saluran. Ketika utas yang mengelola koneksi menerima paket untuk saluran tertentu, ia menggunakan nomor ini untuk memberi tahu broker saluran / sesi mana milik paket itu.
  • Saluran umumnya tidak aman karena tidak masuk akal untuk membaginya di antara utas. Jika Anda memiliki utas lain yang perlu menggunakan broker, saluran baru diperlukan.

Fakta Konsumen

Seorang konsumen adalah objek yang didefinisikan oleh protokol AMQP. Ini bukan saluran atau koneksi, sebaliknya menjadi sesuatu yang aplikasi khusus Anda gunakan sebagai semacam "kotak surat" untuk menjatuhkan pesan.

  • "Menciptakan konsumen" berarti Anda memberi tahu broker (menggunakan saluran melalui koneksi ) bahwa Anda ingin pesan didorong kepada Anda melalui saluran itu. Sebagai tanggapan, broker akan mendaftar bahwa Anda memiliki konsumen di saluran dan mulai mengirimkan pesan kepada Anda.
  • Setiap pesan yang didorong melalui koneksi akan merujuk nomor saluran dan nomor konsumen . Dengan cara itu, utas pengelola koneksi (dalam hal ini, dalam Java API) tahu apa yang harus dilakukan dengan pesan; kemudian, utas penanganan saluran juga tahu apa yang harus dilakukan dengan pesan tersebut.
  • Implementasi konsumen memiliki jumlah variasi terluas, karena ini benar-benar spesifik untuk aplikasi. Dalam implementasi saya, saya memilih untuk melakukan tugas setiap kali pesan tiba melalui konsumen; dengan demikian, saya memiliki utas yang mengelola koneksi, utas yang mengelola saluran (dan dengan ekstensi, konsumen), dan satu atau lebih utas tugas untuk setiap pesan yang dikirim melalui konsumen.
  • Menutup koneksi menutup semua saluran pada koneksi. Menutup saluran menutup semua konsumen di saluran. Dimungkinkan juga untuk membatalkan konsumen (tanpa menutup saluran). Ada berbagai kasus ketika masuk akal untuk melakukan salah satu dari tiga hal ini.
  • Biasanya, implementasi konsumen dalam klien AMQP akan mengalokasikan satu saluran khusus untuk konsumen untuk menghindari konflik dengan kegiatan utas atau kode lainnya (termasuk penerbitan).

Dalam hal apa yang Anda maksud dengan kumpulan utas konsumen, saya menduga bahwa klien Java melakukan sesuatu yang serupa dengan apa yang saya programkan untuk dilakukan klien saya (milik saya didasarkan pada klien .Net, tetapi sangat dimodifikasi).

theMayer
sumber
1
"saluran tidak boleh digabungkan", itulah yang saya cari
ospider
"Karena bersifat sementara, saluran tidak boleh digabungkan dengan aplikasi Anda." - bisakah Anda menjelaskan bagaimana Anda sampai pada kesimpulan ini? Dokumen merekomendasikan pengumpulan saluran jika implementasi "satu saluran per utas" menggunakan terlalu banyak sumber daya, lihat di sini: rabbitmq.com/channels.html#resource-usage
ymas
@ymas - Dokumentasi yang Anda maksud adalah spekulatif, dan menurut saya, panduan yang buruk. Saya membaca kode sumber dan spec protokol. Saluran tidak harus dikumpulkan, titik. Lebih jauh, satu saluran per utas adalah panduan berdasarkan prinsip yang sama. Jika Anda menemukan bahwa Anda memiliki begitu banyak saluran terbuka sehingga server terbatas sumber daya, Anda perlu mengevaluasi kembali arsitektur Anda (yaitu, beralih ke skema ketersediaan tinggi dan / atau mengurangi concurrency).
theMayer
21

Saya menemukan artikel ini yang menjelaskan semua aspek model AMQP, yang salurannya adalah satu. Saya merasa sangat membantu dalam melengkapi pemahaman saya

https://www.rabbitmq.com/tutorials/amqp-concepts.html

Beberapa aplikasi memerlukan beberapa koneksi ke broker AMQP. Namun, tidak diinginkan untuk membiarkan banyak koneksi TCP terbuka pada saat yang sama karena hal itu menghabiskan sumber daya sistem dan membuatnya lebih sulit untuk mengkonfigurasi firewall. Koneksi AMQP 0-9-1 multipleks dengan saluran yang dapat dianggap sebagai "koneksi ringan yang berbagi koneksi TCP tunggal".

Untuk aplikasi yang menggunakan banyak utas / proses untuk pemrosesan, sangat umum untuk membuka saluran baru per utas / proses dan tidak berbagi saluran di antara mereka.

Komunikasi pada saluran tertentu benar-benar terpisah dari komunikasi di saluran lain, oleh karena itu setiap metode AMQP juga membawa nomor saluran yang digunakan klien untuk mengetahui saluran mana yang digunakan untuk metode tersebut (dan dengan demikian, event handler mana yang perlu dipanggil, misalnya) .

CamW
sumber
4

Ada hubungan antara seperti koneksi TCP yang dapat memiliki beberapa Saluran .

Saluran : Ini adalah koneksi virtual di dalam koneksi. Saat menerbitkan atau menggunakan pesan dari antrian - semuanya dilakukan melalui saluran Whereas Connection : Ini adalah koneksi TCP antara aplikasi Anda dan broker RabbitMQ.

Dalam arsitektur multi-threading, Anda mungkin memerlukan koneksi terpisah per utas. Hal itu dapat menyebabkan kurang digunakannya koneksi TCP, juga menambah overhead pada sistem operasi untuk membangun sebanyak mungkin koneksi TCP yang diperlukan selama waktu puncak jaringan. Kinerja sistem dapat dikurangi secara drastis. Di sinilah saluran menjadi berguna, itu menciptakan koneksi virtual di dalam koneksi TCP. Ini secara langsung mengurangi overhead OS, juga memungkinkan kita untuk melakukan operasi asinkron dengan cara yang lebih cepat, andal dan bersamaan. masukkan deskripsi gambar di sini

Atul Jain
sumber