أدوات مطور Node.js. بروتوكول Mqtt للعمل مع مآخذ الويب

تسمح تقنية مأخذ توصيل الويب بإرسال رسائل من خادم إلى عميل في تطبيق ويب أو في تطبيق محمول ، والتي لا يمكن القيام بها باستخدام REST-API. للعمل مع مآخذ الويب ، غالبًا ما يستخدمون مكتبة socket.io ، أو يعمل المطورون مع كائنات مأخذ توصيل الويب الخاصة بالمتصفح الأصلي. سأحاول في هذا المنشور إظهار أن كلا الطريقتين لا يحلان جميع المشكلات ، ومن الأفضل استخدام خوادم متخصصة ، على سبيل المثال ، خادم mqtt (كان يطلق عليه وسيط mqtt من قبل) للعمل مع مآخذ الويب.

في الإنصاف ، ولتجنب النزاعات غير الضرورية ، ألاحظ أنه بالإضافة إلى خادم mqtt ، يمكن استخدام عدد من الخوادم الأخرى ، على سبيل المثال rabbitmq.

يبدو أن تطوير التطبيقات باستخدام مآخذ الويب بسيط للغاية إلى أن نواجه حقيقة تحدث فيها فواصل الاتصال. المهمة الأولى التي يجب حلها هي تتبع فواصل الاتصال واستعادتها. الموقف معقد بسبب حقيقة أنه أثناء انقطاع الاتصال وإعادة الاتصال ، يستمر العميل في إرسال رسائل جديدة ، وكذلك يمكن إرسال رسائل جديدة إلى العميل التي من المرجح أن تضيع.

من الضروري على مستوى التطبيق مراقبة استلام الرسائل ، وتنفيذ التسليم المتكرر. أود بصفة خاصة أن ألفت الانتباه إلى عبارة "على مستوى التطبيق" (ولكن أود أن تكون على مستوى البروتوكول).

بمجرد أن قمنا بإضافة منطق لتتبع تسليم الرسائل ، بدأت جميع الرسائل في الوصول ، ولكن أصبح من الواضح على الفور أن هناك رسائل مكررة ، حيث كان من الممكن استلام الرسالة ، وفقد تأكيد هذه الحقيقة بسبب اتصال غير متصل. وتحتاج إلى مضاعفة مقدار رمز البرنامج لاستبعاد الرسائل المكررة.

بالإضافة إلى تعقيد رمز البرنامج ، تقل فعاليته أيضًا ، وغالبًا ما ينتقدون مكتبة socket.io. إنه ، بطبيعة الحال ، أقل كفاءة من العمل مع مآخذ الويب الأصلية ، على وجه الخصوص ، بسبب وجود منطق إعادة الاتصال وتأكيد تسليم الرسالة (لاحظت على الفور أن منطق إعادة التسليم لا يتم تنفيذه في socket.io).

هناك طريقة أكثر موثوقية وكفاءة تتمثل في رفع هذا المنطق إلى مستوى البروتوكول. ومثل هذا البروتوكول موجود - هو mqtt. تم تطوير الإصدار الأول من بروتوكول mqtt بواسطة Andy Stanford-Clark (IBM) و Arlene Nipper (Arcom) في عام 1999. تم توحيد مواصفات MQTT 3.1.1 بواسطة اتحاد OASIS في عام 2014.

يحتوي بروتوكول mqtt على معلمة "جودة الخدمة" (qos) يمكن أن تأخذ القيم:
0 - يتم تسليم الرسالة إن أمكن ؛
1 - تسليم الرسالة مضمونة ، ولكن قد تكون هناك تكرارات ؛
2 - يتم تسليم الرسالة مضمونة ومضمونة مرة واحدة.

أي أن بروتوكول mqtt يحل المشكلة مع تسليم الرسالة المضمون ، وتتم إزالة هذه المشكلة من جدول الأعمال. ولكن ليس هذا السؤال فقط.

الأداء والقياس.

عند العمل باستخدام مآخذ الويب ، يترك جميع العملاء المتصلين اتصالات مفتوحة للخادم ، حتى إذا لم يكن هناك رسائل حقيقية. هذا التحميل يختلف بطبيعته عن الحمل في REST-API ، والذي يتم تحديده بواسطة تدفق الطلبات. من الصعب محاكاة عبء الاتصالات المفتوحة على مآخذ الويب أثناء مرحلة الاختبار. لذلك ، غالبًا ما يتم الافتراض الخاطئ حول الأداء الكافي للتطبيق بعدد الرسائل المرسلة والمستلمة ، دون مراعاة عبء الحفاظ على عدد كبير من الاتصالات المفتوحة مع العملاء.

إذا قمنا بنقل كل العمل باستخدام مآخذ الويب إلى خادم mqtt متخصص ، فإن تطبيق nodejs لدينا يفتح اتصالًا واحدًا فقط على مقبس الويب (أو tcp ، حيث أن mqtt يدعم كلا البروتوكولين) مع خادم mqtt ، ويمكننا توسيع نطاق تطبيقنا من خلال ربط مثيلات متعددة من nodejs إلى خادم mqtt.

إذا تم استنفاد موارد خادم mqtt واحد ، يمكنك تنظيم مجموعة من خوادم mqtt دون التأثير على التطبيقات على nodejs.

الآن دعنا ننتقل إلى مثال.

خادم mqtt أو الوسيط ، كما كان يسمى في المواصفات السابقة ، يعمل وفقًا لنموذج إرسال الرسائل / الاشتراك في الرسائل. يتم إرسال كل رسالة إلى الموضوع. يشترك المستلم في سلسلة الرسائل. لدى كل من المرسل والمستقبل معرفان: clientId (معرف الجهاز) و userName (اسم المستخدم).

معرف الجهاز مهم ، لأنه مرتبط بالاشتراك وسيتم إرسال الرسائل إليه. اسم المستخدم ، بخلاف معرف الجهاز ، لا يلعب دورًا حاسمًا في تسليم الرسائل ، ويستخدم للتمييز في الوصول إلى الموضوعات.

للعمل مع بروتوكول mqtt على جانب العميل ، يتم استخدام مكتبة github.com/eclipse/paho.mqtt.javascript . هناك العديد من تطبيقات الخادم ، بما في ذلك التطبيقات المجانية. في هذا المثال ، سوف نستخدم خادم emqx ، والذي يعمل من خلال عامل الإرساء (انظر github.com/apapacy/tut-mqtt ).

للاختبار ، قم بإنشاء مستند نضع فيه العميل ، اسم المستخدم ونص الرسالة:

<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> 


يتم إرسال الرسائل في ملف 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); } 


للتحقق ، افتح ملف index.html في المستعرض ، وحدد clientId ، و userName ، ونص الرسالة ، وأرسل عدة رسائل (يمكنك قراءتها في وحدة التحكم ، حيث يرسل العميل رسائل إلى موضوع الاختبار ، ويشترك في هذا الموضوع نفسه).

افتح الآن متصفحًا آخر أو علامة تبويب متصفح أخرى ، وانضم إلى عميل آخر (هذا مهم). أرسل بضع رسائل أخرى من المستعرض الأول ، وتأكد من وصولها لكلا العميلين ، نظرًا لوجودهما مختلف clientId وكلاهما مشترك في اختبار الموضوع.

أغلق الآن المستعرض الثاني (أو علامة تبويب المتصفح الثانية) ، وأرسل بضع رسائل أخرى. بعد ذلك ، أعد فتح المتصفح الثاني ، وانضم إلى clientId نفسه. تأكد من أن سجلات وحدة التحكم قد استلمت جميع الرسائل التي تم إرسالها خلال الفترة التي تم فيها إغلاق المتصفح الثاني (علامة التبويب الثانية). حدث هذا بسبب:

  • عند إرسال رسالة ، تم ضبط مستوى الجودة qos = 2 ؛
  • لقد سبق أن انضمت إلى نفس الموضوع مع نفس clientId عن طريق تعيين qos = 2؛
  • يتم تعيين خيارات الاتصال على cleanSession: false.

يمكن تنزيل نموذج التعليمة البرمجية من المستودع .

apapacy@gmail.com
29 سبتمبر 2019

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


All Articles