MQTT performance evaluation

Hello, I'm new to Node Red and i was wondering if there is any way in node Red to analyze the performance of MQTT connection in terms of reliability, throughput ,latency and such...
And if not what tool should i use for that?

Do you have a particular requirement?

MQTT is extremely reliable and resilient protocol. It's very design was based around unreliable/remote producers.

As for latency, it depends on networks & where your broker is in relation to the client. For example, a localhost broker will deliver packets within a couple of milliseconds. A local network broker will be dependant on your network quality, but typical it will deliver packets to networked clients around 30~40ms

i don't doubt the reliability of mqtt but is just for a school research i have to evaluate the performance of mqtt under different circumstances and scenarios .so i wanted to know if there is a way to do that

I don't know of any analysis tool designed specifically for mqtt and for the measurements you ask for but...

You could setup a few flows that communicate to localhost, local network and internet brokers.

Then add flow logic to measure the time from publish to subscription arrival.

You could add counters for publish and receive & have the flow run every second for 24h then compare the results aft the end.

The limit is your imagination (and coding skills).

This flow will help with time measurement of flows: flow-timer. A simple subflow to measure time taken in parts of your flows. (flow) - Node-RED

These nodes can help with counting : Library - Node-RED

Most brokers actually have some stats published under the $SYS/broker topic.

So you can monitor that.

You could also use InfluxDB, Telegraf and Grafana and get Telegraf to pass those broker stats to InfluxDB and then chart with Grafana.

To see how far you can push your broker, you will likely need a lot of separate threads to push MQTT messages as fast as possible. You will probably need a second device to help. You really need a properly multi-threaded app to do that. Possibly the best approach would be to have a script that sets other scripts going where each inner script sends a continuous stream of messages.

Those stats seem to be indicating an average of 27 messages per second (4kbps) received, 26 mps (210bps) sent, over the 22.3 days since my server was last rebooted. That is a level that I would consider quite low. I wouldn't be surprised if the broker couldn't easily deal with 100x that.

Message latency would be a bit harder to measure. First you would need to make sure that your network isn't saturated. Then you might want a device able to send and receive an mqtt message. Node-RED would be good for this, just make sure neither the device nor node-red is doing anything else. Measure the difference between a msg sent and the same msg received. Take out the network ping latency and you would have an idea - wouldn't be totally accurate of course because of the overheads of Node-RED itself. I fact, if your C++ is up to the job, you might be better off using a network connected microprocessor (e.g. an Arduino) to do the measurements. An Arduino connected to a Pi using a fast serial speed would probably be OK. MPS's are designed for more real-time operation and so would likely have less overheads. Certainly running latency tests while a different device was hammering the broker with increasing frequencies of messages would make for some interesting stats.

Oh, and while this might be a school project, please do report back the findings because a lot of people in this forum would be really interested.

I am new to using mqtt and this subject piqued my interest. I put together a simple test relaying a counter from my local machine to a free remote broker and then back to the same local machine.

[{"id":"40834895.904738","type":"debug","z":"26b5a4eb.db1d34","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1090,"y":1760,"wires":[]},{"id":"469c4e3f.a5deb","type":"mqtt out","z":"26b5a4eb.db1d34","name":"","topic":"unique topic 238ry9w934h9tg8498gni498t9gn","qos":"0","retain":"","broker":"b861a46.db20658","x":620,"y":1760,"wires":[]},{"id":"531112b1.9093bc","type":"mqtt in","z":"26b5a4eb.db1d34","name":"","topic":"unique topic 238ry9w934h9tg8498gni498t9gn","qos":"0","datatype":"json","broker":"b861a46.db20658","x":630,"y":1680,"wires":[["8c28436e.7cd91"]]},{"id":"8c28436e.7cd91","type":"function","z":"26b5a4eb.db1d34","name":"","func":"const subTime = Date.now();\n\nconst { payload: { pubCount, pubTime } } = msg;\n\nconst subCount = context.get('mqtt_sub_count') + 1;\n\ncontext.set('mqtt_sub_count', pubCount);\n\nconst equal = subCount === pubCount;\n\nconst elapsed = subTime - pubTime;\n\nconst fill = !equal ? 'red' : elapsed > 500 ? 'yellow' : 'green';\n\nconst text = `elapsed: ${elapsed}, received: ${pubCount}, expected: ${subCount}`;\n\nnode.status({fill, text});\n\nnode.send({ payload: { pubCount, subCount, pubTime, subTime, elapsed, equal } });","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\nif (typeof context.get('mqtt_sub_count') === 'undefined') {\n    context.set('mqtt_sub_count', 0);\n}","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set('mqtt_sub_count', 0);","x":920,"y":1760,"wires":[["40834895.904738"]]},{"id":"5f2bfe56.a2893","type":"inject","z":"26b5a4eb.db1d34","name":"","props":[{"p":"payload"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":210,"y":1760,"wires":[["9e37bc1c.4f476"]]},{"id":"9e37bc1c.4f476","type":"function","z":"26b5a4eb.db1d34","name":"","func":"let pubCount = context.get('mqtt_pub_count');\n\n++pubCount;\n\ncontext.set('mqtt_pub_count', pubCount);\n\nconst pubTime = Date.now();\n\nnode.send({ payload: { pubCount, pubTime } });","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\nif (typeof context.get('mqtt_pub_count') === 'undefined') {\n    context.set('mqtt_pub_count', 0);\n}","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set('mqtt_pub_count', 0);","x":350,"y":1760,"wires":[["469c4e3f.a5deb"]]},{"id":"cc2643e.57dd1c","type":"inject","z":"26b5a4eb.db1d34","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":191,"y":1879,"wires":[["6378dbb6.fbc844"]]},{"id":"6378dbb6.fbc844","type":"function","z":"26b5a4eb.db1d34","name":"inject garbage","func":"const pubCount = Math.floor(Math.random() * 10000);\n\nconst pubTime = Date.now() - 10000;\n\nnode.send({ payload: { pubCount, pubTime } });","outputs":1,"noerr":0,"initialize":"","finalize":"","x":361,"y":1879,"wires":[["469c4e3f.a5deb"]]},{"id":"b861a46.db20658","type":"mqtt-broker","z":"","name":"","broker":"test.mosquitto.org","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"1","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"1","closeRetain":"false","closePayload":"","willTopic":"","willQos":"1","willRetain":"false","willPayload":""}]

some things to try:

  • increase the frequency rate of sending
  • increase the payload size
  • change the qos setting on publisher and/or subscriber side
  • inject garbage data
  • abuse the free public brokers and see how long it takes to get banned

It seems like a fun experiment.

3 Likes

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.