Introduktion til Gatling

Introduktion

  • Scala - kort introduktion

    • Programmeringssprog

  • Gatling

    • Load testing framework (Apache Benchmark, JMeter…​)

Scala - kort introduktion

scala logo
  • Opfundet af: Martin Odersky professor in programming methods at EPFL, Schweitz

    • Generic Java 1998/99

      • Java 1.3 Compiler javac
      • Java 5 Generics i 2004

  • Multi-paradigme

    • Objektorienteret
    • Funktionelt

  • Afvikles på Java Virtual Machine (JVM)
  • Statically typed: Typer er kendt på compile time

Scala

  • Installation

  • Scala

    • Scala fortolker scala hello-world.scala
    • Scala compiler scalac hello-world.scala

Hello world

println("Hello world!")
// Object er en singleton class
object Main {

    def main(args: Array[String]): Unit = {
        println("Main...")
    }

}

App: Hello world

// App er en Trait der sparer os for at skrive main...
object HelloWorld extends App {

    println("Hello, world!")

}

Variabler

// Mutable variabel
var x : Int = 100

// Immutable værdi (readonly)
val y : Int = 200

// Uden type angivelser
var a = 300
val b = 400

println("X: " + x + ", Y: " + y + ", A: " + a + ", B: " + b)

Funktioner

// Funktions definition
def upperCase(name : String) : String = { return name.toUpperCase() }

// Return er optional for funktioner og det samme er return typen
def lowerCase(name : String) = { name.toLowerCase() }

// One-liners kræver ikke '{}' om funktions body
def add(x : Int, y : Int) : Int = x + y

// Params er immutable (val) og understøtter default værdier
def prefix(name : String, prefix : String = "Mr. ") = {
    prefix + name
}

// Implicit Unit return type
def short() { println("Short") }

Class

abstract class X (val navn : String) {

    var x : Int = 100

    def getName() : String = navn

    def foobar() {}
}

class Y(override val navn : String) extends X(navn) {

    println("Constructor code")

    def this() = this("auxilary constructor")

    override def foobar() = println("foo")
}

val a = new Y("bar")
a.foobar()

val b = new Y()
println(b.getName())

Object

  • Scala har ikke static keyword som Java, i stedet har de object
  • object er en singleton class
// Companion objects

class Bar(foo: String) {
    def foo() : String = foo
}

object Bar {
    def apply(foo: String) = new Bar(foo)
}

// Factory metode, sparer os for new
def x = Bar("Pub")
println(x.foo)
  • Apply er special metode, kommer fra matematik: f(x) applying function f to its argument x

Trait

trait T {
    def foo() = "bar"
}

class P {
    def parent() = "parent"
}

class C extends P with T {}

val cpt = new C()
val pt = new P() with T
println(cpt.foo)
println(cpt.parent())
println(pt.foo())

Case

class C {
    def bar() = "foo"
}

// case sparer os for en del boilerplate code ved at
// tilføjer en række metoder: toString(), hashCode(), equals()
case class D(val f : String = "Hest", val g : String = "vogn") extends C {}

val c = new C()
val d = D()

println(c)
println(d)

Bemærk: case benyttes også ved pattern matching

Scala collections

set
  • Lists
  • Arrays
  • Sets
  • Maps
  • Tuples

Implicit

import scala.language.implicitConversions

case class Point(x : Int, y : Int) {
  // Operator overloading
  def * (mul: Point) : Point = {
    new Point(x * mul.x, y * mul.y)
  }
  def * (mul: Int) : Point = {
    new Point(x * mul, y * mul)
  }
}

implicit def intToPoint(z : Int) : Point = new Point(z, z)

def p1 = new Point(2, 4)
println(p1 * p1) // Out: Point(4,16)
// Mulig uden implicit
println(p1 * 3)  // Out: Point(6,12)
// Kun med implicit
println(3 * p1)  // Out: Point(6,12)

Concurrency

  • Scalas concurrency model er baseret på Actors and message passing
  • Actors har threads, pools og queues
  • Man sender beskeder til Actors med ! hvorved der placeres et objekt på en kø

Concurrency in action

seven languages

Eksempel lånt fra bogen: Seven Languages in Seven Weeks

Concurrency in action - part 1

import scala.io._
import scala.actors._
import Actor._

object PageLoader {
    def getPageSize(url : String) = Source.fromURL(url).mkString.length
}

val urls = List("http://www.amazon.co.uk/",
                "http://www.bbc.co.uk/",
                "http://www.dr.dk/",
                "http://www.cnn.com/" )

Concurrency in action - part 2

def timeMethod(method: () => Unit) = {
    val start = System.nanoTime
    method()
    val end = System.nanoTime
    println("Method took " + (end - start)/1000000000.0 + " seconds.")
}

Concurrency in action - part 3

def getPageSizeConcurrently() = {
    val caller = self

    for(url <- urls) {
        actor { caller ! (url, PageLoader.getPageSize(url)) }
    }

    for(i <- 1 to urls.size) {
        receive {
            case (url, size) =>
                println("Size for " + url + ": " + size)
        }
    }
}

// START:script
timeMethod { getPageSizeConcurrently }

Scala & DSL

  • Scala har en del features der gør det velegnet til DSL’er

    • Generic classes
    • Abstract types
    • Functions as objects
    • Method names as operators
    • Implicit conversions

Gatling

gatling logo
  • Open-source load testing framework
  • Opfundet af: Stéphane Landelle

Installation og afvikling

  • Download og unzip

    • bin/gatling.sh eller bin\gatling.bat

  • Build tool

    • Maven
    • SBT
    • Gradle (3. part plugin)

Intro

  • Bygget på

    • Scala - Object-Oriented Meets Functional
    • Akka - Toolkit and runtime for building highly concurrent, distributed, and resilient message-driven applications
    • Netty - Netty is an asynchronous event-driven network application framework

  • Gatling har et begreb der hedder Scenarier

    • Scenarier kan optages med det medfølgende Recorder GUI program (bin/recorder.sh eller bin\recorder.bat)
    • Eller kodes i Scala DSL

Recorder - setup

gatling small
  • Opsæt Listening port til at proxy igennem
  • Sæt Class Name
  • Sæt Output folder
  • Evt. rediger Blacklist og Infer html resources?

    • Man er typisk ikke interesseret i statiske requests til billeder, Javascript, CSS etc.

Recorder - browser proxy

firefox proxy small
  • Browser uafhængig (Firefox, Chrome, Safari, Opera, IE…​)
  • Indstil browser til at køre gennem proxy

Recorder - optag

gatling running small
  • Klik igennem applikationen i browser
  • Tilføj tags mens test optages - tags placeres i den genererede Scala DSL kode

Hello world

package dk.workbench

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class BasicSimulation extends Simulation {

  val httpConf = http
    .baseURL("http://workbench.dk")
    .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
    .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0")

  val scn = scenario("BasicSimulation")
    .exec(http("request_index")
    .get("/").check(substring("hello world")))
    .pause(5)

  setUp(
    scn.inject(atOnceUsers(1))
  )
  .assertions(
      forAll.responseTime.max.lessThan(6),
      global.failedRequests.percent.lessThan(2)
  )
  .protocols(httpConf)
}

Rapport

analyze
  • Maven: mvn gatling:execute -Dgatling.simulationClass=dk.workbench.BasicSimulation
  • eller: gatling.sh som scanner efter tests ud fra $GATLING_HOME
$ bin/gatling.sh
GATLING_HOME is set to /home/thomas/Downloads/gatling-charts-highcharts-bundle-2.1.7
Choose a simulation number:
     [0] RecordedSimulation
     [1] computerdatabase.BasicSimulation
     [2] computerdatabase.advanced.AdvancedSimulationStep01
     [3] computerdatabase.advanced.AdvancedSimulationStep02
     [4] computerdatabase.advanced.AdvancedSimulationStep03
     [5] computerdatabase.advanced.AdvancedSimulationStep04
     [6] computerdatabase.advanced.AdvancedSimulationStep05

Gatling API

Gatling API - Scenario

gatling scenario

Gatling API - Simulation & Feeder

gatling simulation feeder

Gatling API - Injection

gatling injection

Gatling API - Assertions

gatling assertions

Gatling API - HTTP Action

gatling http action

Gatling API - HTTP Checks

gatling http checks

Gatling API - HTTP Protocol

gatling http protocol

Gatling API - Server Side Event (SSE)

gatling sse

Gatling API - Websockets

gatling websockets

Gatling API - JMS

gatling jms

Setup

oversigt
  • Hvad er det man ønsker at teste?

    • A: Cache (Varnish…​)
    • B: Webserver (Apache, Tomcat, Nginx…​)

      • log (debug, info, error, …​)

    • C: Cache (Memcached, Redis…​)
    • D: Database (MySQL, PostgreSQL…​)

      • Query cache
      • Slow log
      • Queries not using indexes

Demo

  • Gatling Scala API

    • AdvancedSimulation.scala
    • pom.xml

  • Point-n-click

    • recorder.sh
    • gatling.sh

Ressourcer

Andre ressourcer

/