1
votes

I have web server Spring boot + STOMP via WS. Soon this microservice will hit production and I want to measure performance of websocket under load. I want to know how many users my service will handle (and based on that configure autoscaling)

Service is REST API + STOMP topic publisher. I want to write scenario that :

  • in first iteration spawns 1 user, connect via websocket, subscribe to a topic then one message is published and verify that user received it via WS, close connection.
  • in second iteration spawns 10 users, connect via websocket, subscribe to a topic then one message is published and verify that 10 users received it via WS, close connection;
  • in third iteration spawn 100 users, connect via websocket, subscribe to a topic then one message is published and verify that 100 users received it via WS, close connection;
  • and so on.

Then, based on stats, I'll find how many users can process my service. Currently I can spawn users, connect via WS and that's it. How I can create some amount of users and create single http request that will trigger event publication on STOMP topic that this all users are subscribed for?

Here my current test scenario.

package computerdatabase

import java.util.concurrent.TimeUnit
import scala.concurrent.duration._

import io.gatling.core.Predef._
import io.gatling.core.check.Check
import io.gatling.http.Predef._
import io.gatling.http.check.ws.WsTextCheck

import scala.concurrent.duration.{Duration, FiniteDuration}
import scala.util.Random

class TickerSimulation extends Simulation {

  val baseUrl = "https://myserverurl.com"

  val httpProtocol = http
    .baseUrl(baseUrl)
    .inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.woff2""", """.*\.(t|o)tf""", """.*\.png""", """.*detectportal\.firefox\.com.*"""))
    .acceptHeader("*/*")
    .acceptEncodingHeader("gzip, deflate")
    .acceptLanguageHeader("de,en-US;q=0.7,en;q=0.3")
    .userAgentHeader("Mozilla/5.0 (X11; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0")

  def randomServerId(): String = {
    val rand = new Random()
    (1 to 3).map { _ => rand.nextInt(10).toString }.mkString
  }

  def randomSessionId(): String = {
    Random.alphanumeric.take(8).mkString
  }

  val feeder = Iterator.continually(Map(
    "serverId" -> randomServerId(),
    "sessionId" -> randomSessionId()
  ))

  val headers_0 = Map(
    "Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "DNT" -> "1",
    "Pragma" -> "no-cache",
    "Content-Type" -> "application/json",
    "Upgrade-Insecure-Requests" -> "1",
    "Authorization" -> "Basic somebasicauth=")

  val answerCheck = ws.checkTextMessage("Connection acknowledge answer")
    .check(regex("^a.*"))

  val answerEventCheck = ws.checkTextMessage("Game event received")
    .check(regex(".*gameEvent.*"))


  val scn = scenario("WidgetTicker")
    .feed(feeder)
        .exec(http("Get game info ")
          .get("/api/game/35384")
          .headers(headers_0))
        .pause(Random.nextInt(10))
    .exec(ws("WS connection").connect("ws://myserverurl.com/api/sock/${serverId}/${sessionId}/websocket"))
    .pause(1)
    .exec(ws("Connect via STOMP")
      .sendText("[\"CONNECT\\naccept-version:1.1,1.0\\nheart-beat:10000,10000\\n\\n\\u0000\"]")
      .await(60 seconds)(answerCheck)
    ).pause(3)
    .exec(ws("Subscribe")
      .sendText("""["SUBSCRIBE\nid:sub-0\ndestination:/topic/game/35384\n\n\u0000"]""")
      .await(60 seconds)(answerEventCheck)
    )
    .pause(3)
    .exec(ws("WS close").close)


  setUp(scn.inject(
    atOnceUsers(1000)
  )).protocols(httpProtocol)
}

1

1 Answers

1
votes

I've created a topic that the server is writing to every few seconds. Then I'm verifying during simulation that users receive this message. And in such way test pub/sub WebSocket connection

Here what I've come up with:

val answerEventCheck = ws.checkTextMessage("Game event received")
    .check(regex("""^a.*topic\/game\/123.*"""))


val scn = scenario("WidgetTicker")
    .feed(feeder)
    .exec(ws("WS connection").connect("ws://${baseUrl}/api/sock/${serverId}/${sessionId}/websocket"))
    .pause(1)
    .exec(ws("Connect via STOMP")
      .sendText("[\"CONNECT\\naccept-version:1.1,1.0\\nheart-beat:10000,10000\\n\\n\\u0000\"]")
      .await(3 seconds)(answerCheck)
    ).pause(3)
    .exec(ws("Subscribe")
      .sendText("[\"SUBSCRIBE\\nid:sub-0\\ndestination:/topic/game/123\\n\\n\\u0000\"]")
      .await(5 seconds)(answerEventCheck)
    )
    .pause(5)
    .exec(ws("WS close").close)