Dalam dua artikel terakhir , kita berbicara tentang IIoT - Internet industri hal - membangun arsitektur untuk menerima data dari sensor, menyolder sensor itu sendiri. Landasan arsitektur IIoT dan memang semua arsitektur yang bekerja dengan BigData adalah pemrosesan aliran data. Ini didasarkan pada konsep olahpesan dan antrian. Standar untuk bekerja dengan olahpesan sekarang menjadi Apache Kafka. Namun, untuk memahami kelebihannya (dan memahami kekurangannya), akan baik untuk memahami dasar-dasar pengoperasian sistem antrian secara umum, mekanisme operasinya, pola penggunaan, dan fungsionalitas dasar.

Kami menemukan serangkaian artikel luar biasa yang membandingkan fungsionalitas Apache Kafka dan raksasa (yang tidak diacuhkan) di antara sistem antrian - RabbitMQ. Kami telah menerjemahkan serangkaian artikel ini, memberikan mereka komentar dan menambahkannya. Meskipun seri ini ditulis pada bulan Desember 2017, dunia sistem pesan (dan terutama Apache Kafka) berubah begitu cepat sehingga pada musim panas 2018, beberapa hal telah berubah.
Sumber
RabbitMQ vs Kafka
Perpesanan adalah bagian utama dari banyak arsitektur, dan dua pilar di area ini adalah RabbitMQ dan Apache Kafka. Hingga saat ini, Apache Kafka telah menjadi standar industri yang hampir dalam hal pemrosesan data dan analitik, sehingga dalam seri ini kita akan melihat lebih dekat pada RabbitMQ dan Kafka dalam konteks penggunaannya dalam infrastruktur waktu nyata.
Apache Kafka sekarang sedang naik daun, tetapi tampaknya mereka mulai melupakan RabbitMQ. Semua hype berfokus pada Kafka, dan ini terjadi karena alasan yang jelas, tetapi RabbitMQ masih merupakan pilihan yang bagus untuk pengiriman pesan. Salah satu alasan Kafka mengalihkan perhatian ke dirinya sendiri adalah obsesinya yang umum dengan skalabilitas, dan jelas Kafka lebih dapat diukur daripada RabbitMQ, tetapi kebanyakan dari kita tidak peduli dengan skala di mana RabbitMQ memiliki masalah. Sebagian besar dari kita bukan Google atau Facebook. Sebagian besar dari kita berurusan dengan volume pesan harian dari ratusan ribu hingga ratusan juta, dan tidak dengan volume dari miliaran ke triliunan (tetapi omong-omong, ada kasus ketika orang meningkatkan RabbitMQ ke miliaran pesan harian).
Dengan demikian, dalam seri artikel kami, kami tidak akan berbicara tentang kasus-kasus di mana skalabilitas ekstrim diperlukan (dan ini adalah hak prerogatif Kafka), tetapi lebih fokus pada keunggulan unik yang ditawarkan oleh masing-masing sistem yang dipertimbangkan. Menariknya, masing-masing sistem memiliki kelebihannya masing-masing, tetapi pada saat yang sama mereka sangat berbeda satu sama lain. Tentu saja, saya banyak menulis tentang RabbitMQ, tetapi saya meyakinkan Anda bahwa saya tidak memberikan preferensi khusus untuk itu. Saya suka hal-hal yang dibuat dengan baik, dan RabbitMQ dan Kafka keduanya cukup matang, dapat diandalkan dan, ya, sistem pesan yang dapat diskalakan.
Kami akan mulai di tingkat atas, dan kemudian mulai mempelajari berbagai aspek dari dua teknologi ini. Seri artikel ini ditujukan untuk para profesional yang terlibat dalam mengatur sistem pesan atau arsitek / insinyur yang ingin memahami detail dari level bawah dan aplikasinya. Kami tidak akan menulis kode, melainkan fokus pada fungsionalitas yang ditawarkan oleh kedua sistem, templat proses perpesanan yang ditawarkan masing-masing, dan keputusan yang harus dibuat oleh pengembang dan arsitek keputusan.
Pada bagian ini, kita akan melihat apa RabbitMQ dan Apache Kafka, dan pendekatan mereka terhadap olahpesan. Kedua sistem mendekati arsitektur perpesanan dari sudut yang berbeda, masing-masing memiliki kekuatan dan kelemahan. Dalam bab ini, kami tidak akan sampai pada kesimpulan penting, melainkan, kami mengusulkan untuk mengambil artikel ini sebagai manual teknologi untuk pemula, sehingga kami dapat menyelam lebih dalam di artikel seri berikutnya.
Rabbitmq
RabbitMQ adalah sistem manajemen antrian pesan terdistribusi. Didistribusikan, karena biasanya berfungsi sebagai sekelompok node, di mana antrian didistribusikan di antara node dan, secara opsional, direplikasi agar tahan kesalahan dan ketersediaan tinggi. Secara teratur, ini mengimplementasikan AMQP 0.9.1 dan menawarkan protokol lain, seperti STOMP, MQTT dan HTTP melalui modul tambahan.
RabbitMQ menggunakan pendekatan perpesanan klasik dan inovatif. Klasik dalam arti bahwa itu berfokus pada antrian pesan, dan inovatif - dalam kemungkinan routing yang fleksibel. Fitur perutean ini adalah keunggulan uniknya. Menciptakan sistem pengiriman pesan yang cepat, terukur, dan andal merupakan pencapaian tersendiri, tetapi fungsionalitas perutean pengiriman membuatnya sangat luar biasa di antara banyak teknologi pengiriman pesan.
Pertukaran dan antrian
Ulasan yang sangat disederhanakan:
- Penerbit (penerbit) mengirim pesan ke bursa
- Exchange'i mengirim pesan dalam antrian dan ke pertukaran lainnya
- RabbitMQ mengirimkan konfirmasi kepada penerbit setelah menerima pesan
- Penerima (konsumen) memelihara koneksi TCP yang persisten ke RabbitMQ dan mengumumkan antrian mana yang mereka terima
- RabbitMQ mendorong pesan ke penerima
- Penerima mengirim konfirmasi keberhasilan / kesalahan
- Setelah penerimaan berhasil, pesan dihapus dari antrian.
Daftar ini berisi sejumlah besar keputusan yang harus diambil oleh pengembang dan administrator untuk mendapatkan jaminan pengiriman yang mereka butuhkan, karakteristik kinerja, dll., Yang masing-masing akan kita bahas nanti.
Mari kita lihat contoh bekerja dengan satu penerbit, pertukaran, antrian dan penerima:

Fig. 1. Satu penerbit dan satu penerima
Apa yang harus dilakukan jika Anda memiliki beberapa penerbit yang sama
pesan? Bagaimana jika kita memiliki beberapa penerima, yang masing-masing ingin menerima semua pesan?

Fig. 2. Beberapa penerbit, beberapa penerima independen
Seperti yang Anda lihat, penerbit mengirim pesan mereka ke exchanger yang sama, yang mengirim setiap pesan dalam tiga antrian, yang masing-masing memiliki satu penerima. Dalam kasus RabbitMQ, antrian memungkinkan penerima yang berbeda menerima semua pesan. Bandingkan dengan grafik di bawah ini:

Fig. 3. Beberapa penerbit, satu antrian dengan beberapa penerima yang bersaing
Pada Gambar 3, kita melihat tiga penerima yang menggunakan antrian yang sama. Ini adalah penerima yang bersaing, yaitu mereka bersaing untuk menerima pesan dari antrian. Dengan demikian, dapat diharapkan bahwa rata-rata setiap penerima akan menerima sepertiga dari pesan dalam antrian. Kami menggunakan penerima yang bersaing untuk meningkatkan skala sistem pemrosesan pesan kami, dan menggunakan RabbitMQ sangat mudah untuk melakukan ini: menambah atau menghapus penerima berdasarkan permintaan. Tidak peduli berapa banyak penerima pesaing yang Anda miliki, RabbitMQ hanya akan mengirimkan pesan kepada satu penerima.
Kita bisa menggabungkan beras. 2 dan 3 untuk menerima beberapa set penerima yang bersaing, di mana setiap set menerima setiap pesan.

Fig. 4. Beberapa penerbit, beberapa antrian dengan penerima yang bersaing
Panah antara penukar dan antrian disebut binding, dan kami akan membicarakannya lebih detail.
Garansi
RabbitMQ memberikan jaminan "pengiriman satu kali" dan "setidaknya satu pengiriman", tetapi tidak "tepat satu pengiriman".
Catatan Penerjemah: Sebelum Kafka versi 0.11, pengiriman pesan pengiriman yang tepat-sekali tidak tersedia, saat ini, fungsionalitas serupa hadir di Kafka.
Pesan dikirim dalam urutan ketika mereka tiba di antrian (setelah semua, ini adalah definisi dari antrian). Ini tidak menjamin bahwa penyelesaian pemrosesan pesan cocok dengan urutan yang sama ketika Anda memiliki penerima yang bersaing. Ini bukan kesalahan RabbitMQ, tetapi realitas mendasar dari pemrosesan paralel dari serangkaian pesan yang dipesan. Masalah ini dapat diselesaikan dengan menggunakan Konsisten Hashing Exchange, seperti yang akan Anda lihat di bab berikutnya tentang template dan topologi.
Dorong dan ambil penerima sebelumnya
RabbitMQ mendorong pesan ke penerima (ada juga API untuk menarik pesan dari RabbitMQ, tetapi fungsi ini sudah usang sekarang). Ini dapat membanjiri penerima jika pesan masuk dalam antrian lebih cepat daripada penerima dapat memprosesnya. Untuk menghindari hal ini, setiap penerima dapat menetapkan batas prefetch (juga dikenal sebagai batas QoS). Bahkan, batas QoS adalah batas jumlah pesan yang belum diakui oleh penerima. Kerjanya seperti sekering ketika penerima mulai ketinggalan.
Mengapa diputuskan bahwa pesan dalam antrian didorong (dorong), dan tidak dibongkar (tarik)? Pertama, karena ada sedikit waktu tunda. Kedua, idealnya, ketika kami memiliki penerima yang bersaing dari antrian yang sama, kami ingin mendistribusikan beban secara merata di antara mereka. Jika setiap penerima meminta / mengunduh pesan, maka tergantung pada seberapa banyak yang mereka minta, distribusi pekerjaan bisa menjadi agak tidak merata. Semakin tidak merata distribusi pesan, semakin besar penundaan dan semakin hilangnya urutan pesan selama pemrosesan. Faktor-faktor ini mengorientasikan arsitektur RabbitMQ menuju mekanisme push satu pesan pada satu waktu. Ini adalah salah satu batasan penskalaan RabbitMQ. Keterbatasan dimitigasi oleh fakta bahwa konfirmasi dapat dikelompokkan.
Routing
Exchange pada dasarnya adalah router pesan untuk antrian dan / atau pertukaran lainnya. Agar pesan dapat dipindahkan dari pertukaran ke antrian atau ke pertukaran lain, ikatan diperlukan. Pertukaran yang berbeda membutuhkan ikatan yang berbeda. Ada empat jenis pertukaran dan binding terkait:
- Tanpa kipas Mengarahkan semua antrian dan penukar yang terikat untuk menukar submodel Pub standar.
- Langsung (langsung). Merutekan pesan berdasarkan kunci perutean yang dibawanya, ditetapkan oleh penerbit. Kunci perutean adalah string pendek. Penukar langsung mengirim pesan ke / bertukar antrian yang memiliki kunci berpasangan yang sama persis dengan kunci perutean.
- Topik (tematik). Merutekan pesan berdasarkan kunci perutean, tetapi memungkinkan penggunaan pencocokan tidak lengkap (wildcard).
- Header (tajuk). RabbitMQ memungkinkan Anda untuk menambahkan header penerima pesan. Pertukaran header mengirim pesan sesuai dengan nilai header ini. Setiap penjilidan menyertakan kecocokan yang tepat dari nilai header. Anda dapat menambahkan beberapa nilai ke penjilidan dengan nilai APAPUN atau SEMUA yang diperlukan untuk mencocokkan.
- Hashing yang Konsisten. Ini adalah penukar yang hash baik kunci perutean atau header pesan, dan mengirim hanya dalam satu antrian. Ini berguna ketika Anda harus mematuhi pemrosesan jaminan pesanan dan masih dapat mengukur penerima.

Fig. 5. Contoh pertukaran topik
Kami juga akan mempertimbangkan perutean lebih detail, tetapi contoh pertukaran topik diberikan di atas. Dalam contoh ini, penerbit menerbitkan log kesalahan menggunakan format kunci rute LEVEL (Level Kesalahan) .AppName.
Antrian 1 akan menerima semua pesan karena menggunakan nomor wildcard dengan beberapa kata.
Antrian 2 akan menerima level apa pun dari pendataan aplikasi ECommerce.WebUI. Ini menggunakan wildcard *, sehingga menangkap tingkat penamaan topik tunggal (ERROR.Ecommerce.WebUI, NOTICE.ECommerce.WebUI, dll.).
Antrian 3 akan menampilkan semua pesan KESALAHAN dari aplikasi apa pun. Ini menggunakan wildcard # untuk menutup semua aplikasi (ERROR.ECommerce.WebUi, ERROR.SomeApp.SomeSublevel, dll.).
Berkat empat metode perutean pesan dan dengan kemampuan untuk bertukar pesan untuk mengirim pesan ke pertukaran lain, RabbitMQ memungkinkan Anda untuk menggunakan satu set templat pertukaran pesan yang kuat dan fleksibel. Selanjutnya kita akan berbicara tentang pertukaran dengan pertukaran surat mati, tentang pertukaran dan antrian tanpa data (pertukaran sesaat dan antrian), dan RabbitMQ akan memperluas potensi penuhnya.
Pertukaran Tidak Terkirim
Catatan Penerjemah: Ketika pesan dari antrian tidak dapat diterima karena satu dan lain alasan (kekuatan konsumen tidak cukup, masalah jaringan, dll.), Mereka dapat ditunda dan diproses secara terpisah.
Kami dapat mengonfigurasi antrian sehingga pesan dikirim untuk dipertukarkan dalam kondisi berikut:
- Antrian melebihi jumlah pesan yang ditentukan.
- Antrian melebihi jumlah byte yang ditentukan.
- Waktu Pengiriman Pesan (TTL) telah kedaluwarsa. Penerbit dapat mengatur umur pesan, dan antrian itu sendiri juga dapat memiliki TTL yang ditentukan untuk pesan tersebut. Dalam hal ini, TTL yang lebih pendek dari keduanya akan digunakan.
Kami membuat antrian yang terikat untuk bertukar dengan pesan yang tidak terkirim, dan pesan-pesan ini disimpan di sana sampai beberapa tindakan diambil.
Seperti banyak fungsi RabbitMQ, pertukaran dengan pesan yang tidak terkirim memungkinkan untuk menggunakan templat yang awalnya tidak disediakan. Kami dapat menggunakan pesan dan pertukaran TTL dengan pesan yang tidak terkirim untuk menerapkan antrian yang ditangguhkan dan coba lagi antrian.
Penukar dan antrian tanpa data
Pertukaran dan antrian dapat dibuat secara dinamis, dan Anda dapat menetapkan kriteria untuk penghapusan otomatisnya. Ini memungkinkan penggunaan pola seperti RPC berbasis pesan.
Modul tambahan
Plug-in pertama yang mungkin ingin Anda instal adalah plugin manajemen, yang menyediakan server HTTP dengan antarmuka web dan API REST. Sangat mudah untuk menginstal dan memiliki antarmuka yang mudah digunakan. Menyebarkan skrip melalui REST API juga sangat sederhana.
Selain itu:
- Pertukaran Hashing yang Konsisten, Pertukaran Sharding, dan banyak lagi
- protokol seperti STOMP dan MQTT
- kait web
- jenis penukar tambahan
- Integrasi SMTP
Ada banyak hal lain yang dapat dikatakan tentang RabbitMQ, tetapi ini adalah contoh yang baik yang memungkinkan Anda untuk menggambarkan apa yang dapat dilakukan RabbitMQ. Sekarang kita melihat Kafka, yang menggunakan pendekatan yang sama sekali berbeda untuk olahpesan dan, pada saat yang sama, juga memiliki serangkaian fitur unik dan menarik.
Apache kafka
Kafka adalah log komit terdistribusi terdistribusi. Kafka tidak memiliki konsep antrian, yang mungkin tampak aneh pada awalnya, mengingat bahwa itu digunakan sebagai sistem pesan. Antrian telah lama identik dengan sistem pengiriman pesan. Pertama, mari kita lihat apa arti "log komit perubahan terdistribusi, direplikasi":
- Didistribusikan karena Kafka digunakan sebagai sekelompok node, baik untuk toleransi kesalahan dan untuk penskalaan
- Digandakan, karena pesan biasanya direplikasi pada banyak node (server).
- Log komit karena pesan disimpan dalam log yang tersegmentasi dan hanya ditambahkan yang disebut topik. Konsep logging ini adalah keunggulan unik utama Kafka.
Memahami jurnal (dan topik) dan partisi adalah kunci untuk memahami Kafka. Jadi bagaimana perbedaan log yang dipartisi dengan satu set antrian? Mari kita bayangkan seperti apa bentuknya.

Fig. 6 Satu produser, satu segmen, satu penerima
Alih-alih menempatkan pesan dalam antrian FIFO dan memantau status pesan ini dalam antrian, seperti yang dilakukan RabbitMQ, Kafka hanya menambahkannya ke log, dan itu saja.
Pesan tetap ada, terlepas dari apakah pesan itu diterima satu kali atau lebih. Itu dihapus sesuai dengan kebijakan penyimpanan, juga disebut periode waktu jendela. Bagaimana informasi diambil dari topik?
Setiap penerima melacak di mana ia berada di log: ada pointer ke pesan terakhir yang diterima dan pointer ini disebut alamat offset. Penerima mendukung alamat ini melalui pustaka klien, dan tergantung pada versi Kafka, alamat tersebut disimpan di ZooKeeper atau di Kafka itu sendiri.
Ciri khas dari model penjurnalan adalah ia secara instan menghilangkan banyak kesulitan terkait status pengiriman pesan dan, yang lebih penting bagi penerima, memungkinkan mereka untuk memundurkan, mengembalikan, dan menerima pesan di alamat relatif sebelumnya. Misalnya, bayangkan Anda menggunakan layanan yang mengeluarkan faktur yang memperhitungkan pesanan akun yang dilakukan oleh pelanggan. Layanan memiliki kesalahan, dan itu tidak benar menghitung semua tagihan dalam 24 jam. Dengan RabbitMQ terbaik, Anda harus mempublikasikan pesanan ini entah bagaimana hanya pada layanan akun. Tetapi dengan Kafka, Anda cukup memindahkan alamat relatif untuk penerima ini 24 jam yang lalu.
Jadi, mari kita lihat tampilannya ketika ada topik di mana ada satu partisi dan dua penerima, masing-masing harus menerima setiap pesan.

Fig. 7. Satu produser, satu partisi, dua penerima independen
Seperti dapat dilihat dari diagram, dua penerima independen menerima partisi yang sama, tetapi membaca di alamat offset yang berbeda. Mungkin layanan penagihan membutuhkan waktu lebih lama untuk memproses pesan daripada layanan pemberitahuan push. atau mungkin layanan penagihan tidak tersedia untuk beberapa waktu dan mencoba untuk mengejar ketinggalan nanti. Atau mungkin ada kesalahan, dan alamat offset harus ditunda selama beberapa jam.
Sekarang anggaplah bahwa layanan penagihan harus dibagi menjadi tiga bagian, karena tidak dapat mengikuti kecepatan pesan. Dengan RabbitMQ, kami cukup menggunakan dua aplikasi layanan penagihan lagi yang didapat dari antrian penagihan. Tetapi Kafka tidak mendukung penerima yang bersaing di partisi yang sama, blok konkurensi Kafka adalah partisi itu sendiri. Karena itu, jika kita membutuhkan tiga penerima tagihan, kita memerlukan setidaknya tiga partisi. Jadi sekarang kita punya:

Fig. 8. Tiga partisi dan dua grup yang terdiri dari tiga penerima
Dengan demikian, dapat dipahami bahwa Anda membutuhkan sekurang-kurangnya partisi sebanyak penerima horizontal yang paling diskalakan. Mari kita bicara sedikit tentang partisi.
Partisi dan Grup Penerima
Setiap partisi adalah file terpisah di mana urutan pesan dijamin. Ini penting untuk diingat: pesanan pesan dijamin hanya dalam satu partisi. Di masa depan, ini dapat menyebabkan beberapa kontradiksi antara persyaratan untuk antrian pesan dan persyaratan untuk kinerja, karena kinerja di Kafka juga diskalakan oleh partisi. Partisi tidak dapat mendukung penerima yang bersaing, sehingga aplikasi penagihan kami hanya dapat menggunakan satu bagian untuk setiap bagian.
Pesan dapat dialihkan ke segmen dengan algoritma siklik atau melalui fungsi hash: hash (kunci pesan)% jumlah partisi. , , , , , , . .
RabbitMQ. . , RabbitMQ , . , .
RabbitMQ . Kafka , .
, , Kafka , RabbitMQ โ . RabbitMQ , . Kafka , . , , Kafka , .
, , , ( ). , , . , , , .
RabbitMQ โ Consistent Hashing exchange, . Kafka' , Kafka , , , , , -. RabbitMQ , , , .
: , , Id 1000 , Id 1000 . , , . , .
(push) (pull)
RabbitMQ (push) , , . RabbitMQ . , Kafka (pull), . , , Kafka long-polling.
(pull) Kafka - . Kafka , , .
RabbitMQ, , , , . Kafka , .
Kafka /ยป , , . , .

Fig. 9.
, , Kafka :
. 10. ,

, :

Fig. 11.
, , .
, , , , .

Fig. 12.
. .

:
, . , , .
Kafka โ , , , , , . . , . , , .
โ . , 50 . โ . , , , .
, , . , , . , . , , , .
. , , .
, RabbitMQ, Kafka, Kafka . RabbitMQ , , ZooKeeper Consul.
RabbitMQ , Kafka. RabbitMQ, , . : .
. , . . , . . . , , - .
, Kafka, . . , , .
, . RabbitMQ , Kafka .
Kesimpulan
RabbitMQ , . , , . , . , , .
Kafka . , . Kafka , RabbitMQ . , Kafka , RabbitMQ, , .
RabbitMQ.
, , IoT , . : t.me/justiothings