Stress test mqtt broker (HiveMQ CE broker) - jmeter

I have to stress test (load test) an MQTT broker on my machine (or a machine in my network) for getting say the number of clients that can simultaneously remain connected to the broker on that machine, the number of messages that can be simultaneously published by different clients to registered topics and things like these.
How can I achieve this?
I'm quite new at this and have seen some videos about Jmeter but where can I get answers to the questions mentioned above in Jmeter? Just a side note, Jmeter doesn't have inbuilt MQTT support and people have made some plugins for this, namely, https://github.com/xmeter-net/mqtt-jmeter
p.s. Jmeter is not a necessity. I just mentioned it because I found some videos and resources on it.

MQTT Connect sampler opens a connection (one connection per JMeter thread - virtual user) so if you have 2 threads defined in the Thread Group - 2 connections will be open.
MQTT Pub Sampler sends message to the defined topic over the existing connection. If you want to send messages to different topics from the same user - you can parameterize the topic names using i.e. CSV Data Set Config, the same applies to the message payload
When you're done you can call MQTT DisConnect
See Testing the MQTT Messaging Broker for IoT - A Guide article for more detailed information if needed.

Related

how to limit number of connections to IBM MQ

I have a Spring Boot based messaging app sending/receiving JMS messages to/from IBM MQ queue manager.
Basically, it uses MQConnectionFactory to organize connection to IBM MQ and a JmsPoolConnectionFactory from messaginghub:pooledjms to enable JMS connection pool, which is removed from MQConnectionFactory in IBM MQ 7.x
The app uses two different appoach to work with JMS. A "correct" one runs a JMSListener to receive messages and then sends a response on each message using JmsTemplate.send(). And there is a second "troubling" approach, where the app sends requests using JmsTemplate.send() and waits for response using JmsTemplate.readByCorrelId() until received or timed out.
I say troubling because this makes JMS sessions last longer if the response is delayed and could easily exhaust IBM MQ connection limit. Unfortunately, I cannot rewrite the app at the moment to the first approach to resolve the issue.
Now I want to restrict the number of connections in the pool. Of course, the delayed requests will fail but IBM MQ connection limit is more important at the moment, so this is kind of appropriate. The problem is that even if I disable the JmsPoolConnectionFactory, it seems that MQConnectionFactory still opens multiple connections to the query manager.
While profiling the app I see multiple threads RvcThread: com.ibm.mq.jmmqi.remote.impl.RemoteTCPConnection#12433875[...] created by JMSCCMasterThreadPool and corresponding connections to the query manager in MQ Explorer. I wonder why there are many of them in spite of the connection pooling is removed from MQConnectionFactory? I suppose it should open and reuse a single connection then but it is not true in my test.
Disabling "troubling" JmsTemplate.readByCorrelId() and leaving only "correct" way in the app removes these multiple connections (and the waiting threads of course).
Replacing JmsPoolConnectionFactory with SingleConnectionFactory has not effect on the issue.
Is there any way to limit those connections? Is it possible to control max threads in the JMSCCMasterThreadPool as a workaround?
Because it affects other applications your MQ admins probably want you to not exhaust the overall Queue Manager's connection limit (MaxChannels and MaxActiveChannels parameters in qm.ini). They can help you by defining an MQ channel exclusively used by your application. By this, they can limit the number of connections of your application with the MAXINST / MAXINSTC channel parameter. You will get an exception when this number is exhausted which is appropriate as you say. Other applications won’t be affected anymore.

How to set MQTT connect as property in Jmeter and pass it to other thread to post messages on MQTT broker using Pub sampler

I want to set MQTT connect as a Jmeter property and use this connection in other thread which will post messages concurrently to MQTT broker. What I want to implement is
Set MQTT connect as Jmeter property
1 thread which will use the connection to post messages to MQTT broker
MQTT disconnect
What I have done so far is using MQTT connect, Publish samplers and MQTT disconnect in same thread group. But when running multiple threads messages are getting failed to publish for other than thread-1.
Please let me know if there is any way to implement this.
I don't think that:
Moving the connection into another Thread Group
Trying to publish messages concurrently with multiple virtual users over a single connection
is a good idea because well-behaved JMeter test must represent real life usage of your application and each JMeter thread (virtual user) must represent an MQTT-enabled device which establishes its own connection to the broker. If the "messages are getting failed to publish" it indicates problem either with your test setup (parameterization, correlation, whatever) or with your MQTT broker so first of all I would check:
whether all JMeter Variables are having expected values
jmeter.log file
your MQTT broker log file
your system under test log file
See Testing the MQTT Messaging Broker for IoT - A Guide article for more details.
If you're still looking for a way of passing the MQTT connection between thread groups you can do this using JSR223 Test Elements and the following code:
To save the connection into a property:
props.put('connection', vars.getObject('conn'))
To get the connection object from the property:
vars.putObject('conn', props.get('connection'))

Routing messages from Kafka to web socket clients connected to application server cluster

I would like to figure out the best way to route messages from Kafka to web socket clients connected to a load balanced application server cluster. I understand that spring-kafka facilitates consuming and publishing messages to a kafka topic, but how does this work in a load balanced application server scenario when connecting to a distributed kafka topic. Here are the requirements that I would like to satisfy, with the overall goal of facilitating peer to peer messaging in an application with a very, very large volume of users:
Web clients can connect to a tomcat application server via web sockets connection via a load balancer.
Web client can send a message/notification to another client thats connected to different tomcat application server.
Messages are saved in the database and published to a kafka topic/partition that can be consumed by the appropriate web clients/users.
Kafka can be scaled to many brokers with many consumers.
I can see how this can be implemented quite easily in a single application server scenario where the consumer consumes all messages from a kafka topic and re-distributes via spring messaging/websockets. But I can't figure out how this would work in a load balanced application server scenario where there are consumers on each application server forming an overall consumer group for the kafka topic. Assuming that each of the application servers are are consuming sub-sets/partitions of the kafka topic, how do they know which server their intended recipients are connected to? And even if they knew which server their recipients were connected to, how would they route the message to them via websockets?
I considered that the application server load balancing could work by logging users with a particular routing key (users starts with 'A' etc) on to a specific application server, then only consuming messages for users starts with 'A' on that application server. But this seems like it would be difficult to maintain and would make autoscaling very difficult. This seems like it should be an common scenario to implement but I can't find any tools or approaches that fit this scenario.
Sounds like every single consumer should live in its own consumer group. This way all the available consumers are going to consume all the messages sent to the topic. Therefore all the connected websocket clients are going to be notified with those messages.
If you need more complex logic with those messages at
after consuming, e.g. filtering, routing, transforming, aggregating etc., you should consider to involve Spring Integration in you project: https://spring.io/projects/spring-integration
Broadcast to all the consumer may work, but the most efficient solution should route message to the node holds the websocket connection for the target user precisely. As i know, route in a distributed system can be done as follows:
Put the route information in a middleware,such as Redis; Or implement a service by yourself to keep track of all the ssesions. That is, solved in a centralized way.
Let the websocket server find route by themselves. In this circumstance, consensus algorithm like gossip should be taken into consideration.

more than one listener for the queue manager

Can there more than one listener to a queue manager ? I have used one listener/queue manager combination so far and wonder if this possible. This is because we have 2 applications connecting to same queue manager and seems to have problem with that.
There are a couple meanings for the term listener in an MQ context. Let's see if we can clear up some confusion over the terminology and then answer the question as it relates to each.
As defined in the spec, a JMS listener is an object that implements a callback mechanism. It listens on destinations for messages and calls onMessage when they arrive. The destinations may be queues or topics hosted by any JMS-compliant transport provider.
In IBM MQ terms, a listener is a process (runmqlsr) that handles inbound connection requests on a server. Although these can handle a variety of protocols, in practice they are almost exclusively TCP listeners that bind a port (1414 by default) and negotiate connection requests on sockets.
TCP Ports
Tim's answer applies to the second of these contexts. MQ can listen for sockets on multiple ports and indeed it is quite common to do so. Each listener listens on one and only one port. It may listen on that port across all network interfaces or can be bound to a specific network interface. No two listeners can bind to the same combination of interface and port though.
In a B2B context the best practice is to run a dedicated listener for each external business partner to isolate each of their connections across dedicated access paths. Internally I usually recommend separate ports for QMgr-to-QMgr, app-to-QMgr and interactive user connections.
In that sense it is possible to run multiple listeners on a given QMgr. Each of those listeners can accept many connections. Their job is to negotiate the connection then hand the socket off to a Message Channel Agent which talks to the QMgr on behalf of the remotely connected client or QMgr.
JMS Listeners
Based on comments, Ulab refers to JMS listeners. These objects establish a connection to a queue manager and then wait in GET mode for new messages arriving on a destination. On arrival of a message, they call the onMessage method which is an asynchronous callback routine.
As to the question "can there more than one (JMS) listener to a queue manager?" the answer is definitely yes. A multi-threaded application can have multiple listeners connected, multiple application instances can connect at the same time, and many thousands of application connections can be handled by a single queue manager with sufficient memory, disk and CPU available.
Of course, each of these applications is ultimately connected to one or more queues so then the question becomes one of whether they can connect to the same queue.
Many listeners can listen on the same queue so long as they do not get exclusive access to it. Each will receive a portion of the messages arriving.
Listeners on QMgr-managed subscriptions are exclusively attached to a dynamic queue but multiple instances on the same topic will all receive the same messages.
If the queue is clustered and there is more than one instance of it multiple listeners will be required to get all the messages since they will normally be distributed by MQ workload distribution across those instances.
Yes, you can create as many listeners as you wish:
http://www.ibm.com/support/knowledgecenter/SSFKSJ_9.0.0/com.ibm.mq.explorer.doc/e_listener.htm
However, there is no reason why two applications can't connect to the queue manager via the same listener (on the same port). What problem have you run into?

Do I need to run Mosquitto to interact with a remote mosquitto broker

I am new to mqtt and would like to get my head around something.
I need to get messages from (subscribe to) topics from a remote mosquitto broker. The documentation for the service says I need to run a mosquitto broker on my server.
If I understand correctly then a script that uses the mqtt gem and manages to connect using something like this:
MQTT::Client.connect(conn_opts) do |c|
# The block will be called when you messages arrive to the topic
c.get('test') do |topic, message|
puts "#{topic}: #{message}"
end
end
IS a broker? Do I need to run mosquitto on my machine or can I get away with just a script and mqtt?
The doc describes the architecture and includes these lines:
The 3rd party platform needs an MQTT broker installed that will allow
communication with the different boxes on our servers. The broker on our servers will
initiate the connection and provide the credentials to allow
bidirectional communication.
The architecture I have in mind is a scheduled background process, using ruby-mqtt, that will spawn, connect with the remote mosquitto server and pull down new messages in batches before finishing. Does this sound like a reasonable approach for getting messages from a remote mosquitto broker?
I have a sneaky suspicion there is something I am not getting... any help/direction will be appreciated. Thanks!
No, you do not need a local MQTT server, you can connect directly to the remote server from your ruby script.
It is typical to keep the MQTT client running all the time, and not just download periodically using cron. Although I imagine that could work, providing you are using QoS 1/2 and disable clean sessions, so that messages are retained on the remote server. Despite its name, MQTT is not a message queuing protocol, it is a publish/subscribe protocol, so it is possible at the remote server will not allow you to build up a large pool of messages.
It may however be desirable to have a local MQTT server (eg mosquitto):
* You local MQTT server could deal with the storing of messages to disk until ruby is ready for them
* It allows multiple local clients to receive the same message without the remote server having to send it over the network multiple times
* Multiple local clients can send messages to each other, even when the remote network is down
Also be warned that ruby-mqtt doesn't support QoS 1 properly yet and also doesn't support persisting of messages or automatic reconnects, so a local mosquitto instance could solve some of those problems for you.

Resources