MQTT gatling multiple connections to different devices

79 views
Skip to first unread message

Karthik Nathan

unread,
Oct 25, 2021, 2:27:23 PM10/25/21
to Gatling User Group
Hello, 

According to the documentation, I can understand the device information are provided at the protocol level, so the load generated will be only for the same connection. Would it be possible to create load for multiple connections, i.e., something like mqtt("Connecting").connect.clientId("xx").credentials("xx","xx")?

Thanks,
Karthik Nathan

Stéphane LANDELLE

unread,
Oct 25, 2021, 3:08:16 PM10/25/21
to gat...@googlegroups.com
clientId and credentials' username and password all take Expressions so they are dynamic fields and you can pass Gatling EL String or functions.


--

Stéphane Landelle

Chief Technical Officer

   

slan...@gatling.io
gatling.io
   
facebook twitter linkedin 


--
You received this message because you are subscribed to the Google Groups "Gatling User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gatling+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gatling/12035325-234d-4754-92c0-3bf5eb853d11n%40googlegroups.com.

Karthik Nathan

unread,
Oct 25, 2021, 3:21:25 PM10/25/21
to gat...@googlegroups.com
The credentials get configured at the SetUp right, so if I needed to have multiple devices, like 600 connected to a broker, how would that work? According to my understanding mqtt("connect") does not take in clientid and credentials, or do they?

According to https://github.com/gatling/gatling/blob/main/gatling-mqtt/src/main/scala/io/gatling/mqtt/action/builder/ConnectBuilder.scala, the mqtt request api(mqtt("requestName")) does not have the parameters that mqttProtocol has access to namely clientId("id") and credentials("${userName}", "${password}").

Thanks,
Karthik Nathan


You received this message because you are subscribed to a topic in the Google Groups "Gatling User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/gatling/q5uXCinjRDA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to gatling+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gatling/CAJw%3DiaR3BTW7PpOO1dJ4wAtsthPxL2TbYJF8uXWj-KNj9ahshA%40mail.gmail.com.

Stéphane LANDELLE

unread,
Oct 25, 2021, 3:24:29 PM10/25/21
to gat...@googlegroups.com
Each virtual user simulates a device.
Inject the clientId, userName and password attribute, eg with a feeder, before the connect action.

--

Stéphane Landelle

Chief Technical Officer

   

slan...@gatling.io
gatling.io
   
facebook twitter linkedin 

Karthik Nathan

unread,
Oct 25, 2021, 3:35:15 PM10/25/21
to gat...@googlegroups.com
The thing is that I create these devices via a http request then use the session object to retreive the credentials, an example is shown below:

scenario("MQTT Test").exec(
http("Set up MQTT Connections")
.post(hostName)
.body(StringBody("{\"name\": \"do l\",\"permissions\": [{\"channelId\":\""+channelId+"\",\"publish\": true, \"subscribe\": true}],\"description\": \"test\"}"))
.exec((session: io.gatling.core.session.Session) => {
mqtt("Connecting").connect
.cleanSession(true)
.clientId(session("clientId").as[String])
.credentials(session("username").as[String],session("password").as[String]))
.exec(mqtt("Subscribing").subscribe("channels/"+channelId+"/subscribe"))
})

Now is the above usage of the connect correct or can connect not use those parameters, "clientid and credentials".

Thanks,
Karthik Nathan



Stéphane LANDELLE

unread,
Oct 25, 2021, 3:40:37 PM10/25/21
to gat...@googlegroups.com
You're not using the Gatling DSL properly.


Gatling DSL components are immutable ActionBuilder(s) that have to be chained altogether and are only built once on startup. The result is a workflow chain of Action(s). These builders don’t do anything by themselves, they don’t trigger any side effect, they are just definitions. As a result, creating such DSL components at runtime in functions is completely meaningless. If you want conditional paths in your execution flow, use the proper DSL components (doIfrandomSwitch, etc)
exec { session =>
  if (someSessionBasedCondition(session)) {
    // just create a builder that is immediately discarded, hence doesn't do anything
    // you should be using a doIf here
    http("Get Homepage").get("http://github.com/gatling/gatling")
  }
  session
}
This is correct:

scenario("MQTT Test").exec(
            http("Set up MQTT Connections")
            .post(hostName)
            .body(StringBody("{\"name\": \"do l\",\"permissions\": [{\"channelId\":\""+channelId+"\",\"publish\": true, \"subscribe\": true}],\"description\": \"test\"}"))
            .exec(
              mqtt("Connecting").connect
              .cleanSession(true)
              .clientId("${clientId}")
              .credentials("${username}", "${password}")

            )
            .exec(mqtt("Subscribing").subscribe("channels/"+channelId+"/subscribe"))

or if you really want to use functions:

scenario("MQTT Test").exec(
            http("Set up MQTT Connections")
            .post(hostName)
            .body(StringBody("{\"name\": \"do l\",\"permissions\": [{\"channelId\":\""+channelId+"\",\"publish\": true, \"subscribe\": true}],\"description\": \"test\"}"))
            .exec(
              mqtt("Connecting").connect
              .cleanSession(true)
              .clientId(session => session("clientId").as[String])
              .credentials(session => session("username").as[String], session => session("password").as[String])
            )
            .exec(mqtt("Subscribing").subscribe("channels/"+channelId+"/subscribe"))


--

Stéphane Landelle

Chief Technical Officer

   

slan...@gatling.io
gatling.io
   
facebook twitter linkedin 

Karthik Nathan

unread,
Nov 3, 2021, 5:35:49 PM11/3/21
to gat...@googlegroups.com
Thanks for the information. To clarify, to use gatling mqtt on enterprise, do we need to use the gatling-mqtt maven plugin? if so, is there a specific version as I see that there is some interference causing by that dependency:
 full rebuild may help if 'AssertionSupport.class' was compiled against an incompatible version of io.gatling.commons.shared.unstable.model.stats.assertion.
6924 [ERROR] import io.gatling.core.Predef._
Karthik Nathan


Stéphane LANDELLE

unread,
Nov 3, 2021, 5:39:17 PM11/3/21
to gat...@googlegroups.com
You must use the same version for gatling-mqtt and the rest of your Gatling modules.
And then, you must use a version that's supported in Gatling Enterprise releases. Latest Gatling Enterprise 1.15.3 supports Gatling 3.3, 3.4., 3.5 and 3.6.


--

Stéphane Landelle

Chief Technical Officer

   

slan...@gatling.io
gatling.io
   
facebook twitter linkedin 

Karthik Nathan

unread,
Nov 4, 2021, 12:28:56 PM11/4/21
to gat...@googlegroups.com
I'm sorry, but I am still confused on how to use the mqtt module in maven. I have imported following dependencies:
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-mqtt</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.2.1</version>
</dependency>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<!-- so maven can compile your scala code -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>4.4.1</version>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<recompileMode>all</recompileMode>
<jvmArgs>
<jvmArg>-Xss100M</jvmArg>
</jvmArgs>
<args>
<arg>-target:jvm-1.8</arg>
<arg>-deprecation</arg>
<arg>-feature</arg>
<arg>-unchecked</arg>
<arg>-language:implicitConversions</arg>
<arg>-language:postfixOps</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>

<!-- so maven can build a package for Gatling Enterprise -->
<plugin>
<groupId>io.gatling.frontline</groupId>
<artifactId>frontline-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<configFolder>${project.basedir}/src/test/resources</configFolder>
<runMultipleSimulations>true</runMultipleSimulations>
<includes>
<simulationClass>
${simulation_class}
</simulationClass>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Is there a plugin for Gatling Enterprise that I need to use? Also I have access to an EC2 instance with Frontline AMI, so I would need to compile the binary and host it right so that frontline can fetch it?
Karthik Nathan


Stéphane LANDELLE

unread,
Nov 4, 2021, 12:31:43 PM11/4/21
to gat...@googlegroups.com
From my previous email: You must use the same version for gatling-mqtt and the rest of your Gatling modules.

Yet, you still have

<groupId>io.gatling</groupId>
<artifactId>gatling-mqtt</artifactId>
<version>3.6.1</version>

<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.2.1</version>

You must use 3.6.1 everywhere.

--

Stéphane Landelle

Chief Technical Officer

   

slan...@gatling.io
gatling.io
   
facebook twitter linkedin 


Karthik Nathan

unread,
Nov 4, 2021, 1:39:32 PM11/4/21
to gat...@googlegroups.com
Thanks for the clarification. 
According to your response for have multiple devices connect.
This is correct:

scenario("MQTT Test").exec(
            http("Set up MQTT Connections")
            .post(hostName)
            .body(StringBody("{\"name\": \"do l\",\"permissions\": [{\"channelId\":\""+channelId+"\",\"publish\": true, \"subscribe\": true}],\"description\": \"test\"}"))
            .exec(
              mqtt("Connecting").connect
              .cleanSession(true)
              .clientId("${clientId}")
              .credentials("${username}", "${password}")
            )
            .exec(mqtt("Subscribing").subscribe("channels/"+channelId+"/subscribe"))

or if you really want to use functions:

scenario("MQTT Test").exec(
            http("Set up MQTT Connections")
            .post(hostName)
            .body(StringBody("{\"name\": \"do l\",\"permissions\": [{\"channelId\":\""+channelId+"\",\"publish\": true, \"subscribe\": true}],\"description\": \"test\"}"))
            .exec(
              mqtt("Connecting").connect
              .cleanSession(true)
              .clientId(session => session("clientId").as[String])
              .credentials(session => session("username").as[String], session => session("password").as[String])
            )
            .exec(mqtt("Subscribing").subscribe("channels/"+channelId+"/subscribe"))

error: value cleanSession is not a member of io.gatling.mqtt.action.builder.ConnectBuilder
3248 [ERROR] possible cause: maybe a semicolon is missing before `value cleanSession`?
3249 [ERROR]               .cleanSession(true)

I see that clientId, credentials and cleanSession are not part of the connectBuilder action. If this is the case how do we create multiple connections for multiple devices?

I do recall that we can use a feeder before the connect action to create the connections. In the example here:

What is inside the csv file? 
Karthik Nathan


Karthik Nathan

unread,
Nov 11, 2021, 5:21:37 PM11/11/21
to Gatling User Group
Is it possible to use session variables inside the mqttProtocol? I have a file of clientIds,usernames and passwords and need to pass them to mqtt protocol's clientId and credentials method. Is it possible to do this?
Reply all
Reply to author
Forward
0 new messages