Here is my updated Gatling directory structure
gatling
gatling/conf
gatling/conf/production
gatling/conf/production/gatling.conf
gatling/conf/staging
gatling/conf/staging/gatling.conf
gatling/Dockerfile
gatling/results
gatling/user-files
gatling/user-files/data
gatling/user-files/data/production-urls.csv
gatling/user-files/data/staging-urls.csv
gatling/user-files/simulations
gatling/user-files/simulations/development
gatling/user-files/simulations/production
gatling/user-files/simulations/production/Simulation.scala
gatling/user-files/simulations/staging
gatling/user-files/simulations/staging/Simulation.scala
Note that I created a separate directory under simulations for each environment (development, staging, production), each with its own simulation files.
I also created a data directory under user-files, because that is the default location for CSV files used by Gatling feeders.
Most importantly, I created a separate configuration directory (staging, production) under gatling/conf, each directory containing its own customized gatling.conf file. I started by copying the gatling-defaults.conf file from GitHub to gatling/conf/staging/gatling.conf and gatling/conf/production/gatling.conf respectively.
Here is what I customized in staging/gatling.conf:
mute = true # When set to true, don't ask for simulation name nor run description
simulations = user-files/simulations/staging
I customized production/gatling.conf in a similar way:
mute = true # When set to true, don't ask for simulation name nor run description
simulations = user-files/simulations/production
Setting mute to true is important because without it, running Gatling in a Docker container was segfaulting while waiting for user input for the simulation ID:
Select simulation id (default is 'gatlingsimulation'). Accepted characters are a-z, A-Z, 0-9, - and _
Exception in thread "main" java.lang.NullPointerException
at io.gatling.app.Selection$Selector.loop$1(Selection.scala:127)
at io.gatling.app.Selection$Selector.askSimulationId(Selection.scala:135)
at io.gatling.app.Selection$Selector.selection(Selection.scala:50)
at io.gatling.app.Selection$.apply(Selection.scala:33)
at io.gatling.app.Gatling.runIfNecessary(Gatling.scala:75)
at io.gatling.app.Gatling.start(Gatling.scala:65)
at io.gatling.app.Gatling$.start(Gatling.scala:57)
at io.gatling.app.Gatling$.fromArgs(Gatling.scala:49)
at io.gatling.app.Gatling$.main(Gatling.scala:43)
at io.gatling.app.Gatling.main(Gatling.scala)
The other customization was to point the simulations attribute to the specific staging or production sub-directories.
Since the CSV files containing URLs to be load tested are also environment-specific, I modified the Simulation.scala files to take this into account. I also added 2 JAVA_OPTS variables that can be passed at runtime for HTTP basic authentication. Here is the new Crawl object (compare with the one from my previous post):
object Crawl {
val feeder = csv("staging-urls.csv").random
val userName = System.getProperty("username")
val userPass = System.getProperty("password")
val crawl = exec(feed(feeder)
.exec(http("${loc}")
.get("${loc}").basicAuth(userName, userPass)
))
}
One more thing is needed: to make Gatling use a specific configuration file instead of its default one, which is conf/gatling.conf. To do that, I set GATLING_CONF as an ENV variable in the Dockerfile, so it can be passed as a 'docker run' command line parameter. Here is the Dockerfile:
# Gatling is a highly capable load testing tool.
#
# Documentation: http://gatling.io/docs/2.2.2/
# Cheat sheet: http://gatling.io/#/cheat-sheet/2.2.2
FROM java:8-jdk-alpine
MAINTAINER Denis Vazhenin
# working directory for gatling
WORKDIR /opt
# gating version
ENV GATLING_VERSION 2.2.2
# create directory for gatling install
RUN mkdir -p gatling
# install gatling
RUN apk add --update wget && \
mkdir -p /tmp/downloads && \
wget -q -O /tmp/downloads/gatling-$GATLING_VERSION.zip \
https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/$GATLING_VERSION/gatling-charts-highcharts-bundle-$GATLING_VERSION-bundle.zip && \
mkdir -p /tmp/archive && cd /tmp/archive && \
unzip /tmp/downloads/gatling-$GATLING_VERSION.zip && \
mv /tmp/archive/gatling-charts-highcharts-bundle-$GATLING_VERSION/* /opt/gatling/
# change context to gatling directory
WORKDIR /opt/gatling
# set directories below to be mountable from host
VOLUME ["/opt/gatling/conf", "/opt/gatling/results", "/opt/gatling/user-files"]
# set environment variables
ENV PATH /opt/gatling/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV GATLING_HOME /opt/gatling
ENV GATLING_CONF /opt/gatling/conf
ENV JAVA_OPTS ""
ENTRYPOINT ["gatling.sh"]
Finally, here is how I invoke 'docker run' to tie everything together:
docker run --rm -v ${WORKSPACE}/gatling/conf:/opt/gatling/conf -v ${WORKSPACE}/gatling/user-files:/opt/gatling/user-files -v ${WORKSPACE}/gatling/results:/opt/gatling/results -e GATLING_CONF="/opt/gatling/conf/staging" -e JAVA_OPTS="-Dusers=$USERS -Dduration=$DURATION -Dusername=myusername -Dpassword=mypass" /PATH/TO/DOCKER/REGISTRY/gatling
Happy load testing!
1 comment:
Hi Grig,
I'm very new on load testing using gatling.
Just wondering, do you prefer to run this docker-gatling as a single container on each host/node (we could maximize the throughput for each gatling script) on each host/node,
or it is better to use multiple (hundreds) of containers on each host/node, but with more smaller gatling's load?
how about the saturation?
Post a Comment