Alat pengembang Node.js. Protokol Mqtt untuk bekerja dengan soket web

Teknologi soket web memungkinkan pengiriman pesan dari server ke klien dalam aplikasi web atau dalam aplikasi seluler, yang tidak dapat dilakukan menggunakan REST-API. Untuk bekerja dengan soket web, mereka sering menggunakan perpustakaan socket.io, atau pengembang bekerja dengan objek soket web browser asli. Dalam posting ini, saya akan mencoba menunjukkan bahwa kedua cara tidak menyelesaikan semua masalah, dan jauh lebih baik menggunakan server khusus, misalnya, server mqtt (sebelumnya disebut pialang mqtt) untuk bekerja dengan soket web.

Dalam keadilan, dan untuk menghindari perselisihan yang tidak perlu, saya perhatikan bahwa selain server mqtt, sejumlah server lain dapat digunakan, misalnya rabbitmq.

Mengembangkan aplikasi menggunakan soket web tampaknya sangat sederhana sampai kita menemukan kenyataan di mana koneksi sering terputus. Tugas pertama yang harus dipecahkan adalah melacak jeda koneksi dan memulihkannya. Situasi ini diperumit oleh kenyataan bahwa selama pemutusan dan penyambungan kembali, klien terus mengirim pesan baru, serta pesan baru dapat dikirim ke klien yang lebih mungkin hilang.

Diperlukan pada tingkat aplikasi untuk memantau penerimaan pesan, dan untuk menerapkan pengiriman berulang mereka. Saya terutama ingin menarik perhatian pada frase "di level aplikasi" (tapi saya ingin berada di level protokol).

Segera setelah kami menambahkan logika untuk melacak pengiriman pesan, semua pesan mulai berdatangan, tetapi segera menjadi jelas bahwa ada pesan duplikat, karena pesan tersebut dapat diterima, dan konfirmasi fakta ini hilang karena koneksi terputus. Dan Anda perlu menggandakan jumlah kode program untuk mengecualikan pesan duplikat.

Seiring dengan komplikasi kode program, efisiensinya juga menurun, yang sering mereka kritik terhadap socket.io library. Ini, tentu saja, kurang efektif daripada bekerja dengan soket web asli, khususnya, karena adanya logika koneksi ulang dan konfirmasi pengiriman pesan (saya segera melihat bahwa logika pengiriman ulang tidak diterapkan pada socket.io).

Cara yang lebih andal dan efisien adalah membawa logika ini ke tingkat protokol. Dan protokol seperti itu ada - itu adalah mqtt. Versi pertama dari protokol mqtt dikembangkan oleh Andy Stanford-Clark (IBM) dan Arlene Nipper (Arcom) pada tahun 1999. Spesifikasi MQTT 3.1.1 distandarisasi oleh konsorsium OASIS pada tahun 2014.

Protokol mqtt memiliki parameter "kualitas layanan" (qos) yang dapat mengambil nilai:
0 - pesan dikirimkan jika memungkinkan;
1 - pesan yang dikirim dijamin, tetapi mungkin ada duplikat;
2 - pesan dikirim dijamin dan dijamin sekali.

Yaitu, protokol mqtt memecahkan masalah dengan pengiriman pesan yang dijamin, dan masalah ini dihapus dari agenda. Tapi bukan hanya pertanyaan ini.

Performa dan penskalaan.

Saat bekerja dengan soket web, semua klien yang terhubung meninggalkan koneksi terbuka ke server, bahkan jika tidak ada pesan nyata. Beban ini secara inheren berbeda dari beban di REST-API, yang ditentukan oleh aliran permintaan. Beban koneksi terbuka pada soket web sulit untuk ditiru selama fase pengujian. Oleh karena itu, asumsi yang keliru sering dibuat tentang kinerja aplikasi yang cukup dengan jumlah pesan yang dikirim dan diterima, tanpa memperhitungkan beban mempertahankan sejumlah besar koneksi terbuka dengan klien.

Jika kami mentransfer semua pekerjaan dengan soket web ke server mqtt khusus, maka aplikasi nodejs kami hanya membuka satu koneksi pada soket web (atau tcp, karena mqtt mendukung kedua protokol) dengan server mqtt, dan kami dapat skala aplikasi kita dengan menghubungkan beberapa instance dari nodejs ke server mqtt.

Jika sumber daya dari satu server mqtt habis, Anda dapat mengatur sekelompok server mqtt tanpa mempengaruhi aplikasi pada nodejs.

Sekarang mari kita beralih ke contoh.

Server atau broker mqtt, seperti yang disebut dalam spesifikasi sebelumnya, berfungsi sesuai dengan model pengiriman pesan / berlangganan pesan. Setiap pesan dikirim ke topik. Penerima berlangganan utas pesan. Baik pengirim dan penerima memiliki dua pengidentifikasi: clientId (pengidentifikasi perangkat) dan nama pengguna (nama pengguna).

Pengidentifikasi perangkat penting, karena dikaitkan dengan langganan dan pesan akan dikirim ke sana. Nama pengguna, tidak seperti pengenal perangkat, tidak memainkan peran yang menentukan dalam pengiriman pesan, dan digunakan untuk membedakan akses ke topik.

Untuk bekerja dengan protokol mqtt pada sisi klien, pustaka github.com/eclipse/paho.mqtt.javascript digunakan. Ada beberapa implementasi server, termasuk yang gratis. Dalam contoh ini, kita akan menggunakan server emqx, yang dijalankan melalui docker-compose (lihat github.com/apapacy/tut-mqtt ).

Untuk pengujian, buat dokumen di mana kami akan mengatur clientId, userName dan teks pesan:

<script src="/paho-mqtt.js"></script> <script src="/messages.js"></script> <form name="sender" onsubmit="return false"> <input type="text" name="user"> <input type="text" name="client"> <input type="text" name="message"> <input type="button" onclick="connect()" value="connect"> <input type="button" onclick="send()" value="send"> </form> 


Mengirim pesan diimplementasikan dalam file message.js:

 var client; var connectOptions = { timeout: 30, reconnect: true, cleanSession: false, mqttVersion: 4, keepAliveInterval: 10, onSuccess: onConnect, onFailure: onFailure } function connect() { try { client = new Paho.Client('localhost', 8083, '/mqtt', document.forms.sender.client.value); connectOptions.userName = document.forms.sender.user.value; client.connect(connectOptions); } catch (ex) { console.log(ex); } } function onConnect() { console.log('on connect'); client.onMessageArrived = function(message) { console.log("onMessageArrived: " + message.payloadString); } client.subscribe("test", { qos: 2 }); } function onFailure(err) { console.log('on failure', JSON.stringify(err)); } function send() { var message = new Paho.Message(document.forms.sender.message.value); message.destinationName = "test"; message.qos = 2; client.send(message); } 


Untuk memeriksa, buka file index.html di browser, tentukan clientId, nama pengguna, teks pesan, dan kirim beberapa pesan (Anda dapat membacanya di konsol, saat klien mengirim pesan ke topik pengujian, dan berlangganan ke topik ini sendiri).

Sekarang buka browser lain atau tab browser lain, dan gabung dengan clientId lainnya (ini penting). Kirim beberapa pesan lagi dari browser pertama, dan pastikan mereka datang ke kedua klien, karena mereka memiliki clientId yang berbeda dan mereka berlangganan tes topik.

Sekarang tutup browser kedua (atau tab browser kedua), dan kirim beberapa pesan lagi. Setelah itu, buka kembali browser kedua, dan bergabung dengan clientId yang sama. Pastikan di log konsol bahwa Anda telah menerima semua pesan yang dikirim selama periode ketika browser kedua (tab kedua) ditutup. Ini terjadi karena:

  • Saat mengirim pesan, tingkat kualitas qos = 2 ditetapkan;
  • Anda sebelumnya telah bergabung dengan topik yang sama dengan clientId yang sama dengan menetapkan qos = 2;
  • Opsi koneksi diatur ke cleanSession: false.

Kode sampel dapat diunduh dari repositori .

apapacy@gmail.com
29 September 2019

Source: https://habr.com/ru/post/id469315/


All Articles