问题
I am new to Gatling (2.1.2) and want to do a small prototype project to show to my colleagues.
According to the quick start page, there are several ways I can run a simulation with Gatling:
- decompress the Gatling bundle into a folder and drop my simulation files into user-files/simulations folder. bin/gatling.sh will compile and run the simulation files.
- use the
gatling-maven-plugin
maven plugin to execute the simulation. - create a project with
gatling-highcharts-maven-archetype
, and run the Engine class.
and I found those problems
For 1, it is hard to add dependencies for simulation classes. I have to figure out what the jars are needed and drop them to the lib folder.
For 2, it requires maven to be installed.
For 3, it only runs from an IDE
I just want a simple executable JAR file with all the dependencies bundled together (my simulation, Gatling and third party), and run it from any machine (like EC2 instances).
Is there a way to achieve this?
Update 1:
I tried method 3, but moving all the project files from test
folder to main
, and used maven-assembly-plugin
to build a jar with dependencies. When I tried to run the file, I got the following error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at Engine$.delayedEndpoint$Engine$1(Engine.scala:7)
at Engine$delayedInit$body.apply(Engine.scala:4)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at Engine$.main(Engine.scala:4)
at Engine.main(Engine.scala)
Caused by: java.nio.file.FileSystemNotFoundException
at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
at java.nio.file.Paths.get(Paths.java:143)
at io.gatling.core.util.PathHelper$.uri2path(PathHelper.scala:32)
at IDEPathHelper$.<init>(IDEPathHelper.scala:7)
at IDEPathHelper$.<clinit>(IDEPathHelper.scala)
... 11 more
I guess this is something to do with Gatling configuration, but don't know what has gone wrong.
回答1:
I tried to do something similar. I could not use Maven as well. I will try to remember how I did this.
1) I have configured maven-assembly-plugin to generate single JAR with dependencies like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
You need to ensure all required libraries (gatling, scala runtime, zinc compiler) are present on your resulting classpath.
2) Check the scope of your dependencies as Maven packs only classes defined with scope=compile by default. The most simple way is probably to use no test dependencies.
3) Create a launch script, e.g. launch.sh. It should contain something like this:
#!/bin/sh
USER_ARGS="-Dsomething=$1"
COMPILATION_CLASSPATH=`find -L ./target -maxdepth 1 -name "*.jar" -type f -exec printf :{} ';'`
JAVA_OPTS="-server -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -Xms512M -Xmx2048M -XX:+HeapDumpOnOutOfMemoryError -XX:+AggressiveOpts -XX:+OptimizeStringConcat -XX:+UseFastAccessorMethods -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false ${JAVA_OPTS}"
java $JAVA_OPTS $USER_ARGS -cp $COMPILATION_CLASSPATH io.gatling.app.Gatling -s your.simulation.FullClassName
To explain, I took gatling`s own launch script for inspiration. Note mainly the presence of target directory in classpath parameter definition.
4) Compile your compiled target directory and launch.sh to a single directory and distribute this (e.g. as archive). Then you can the scenarios by executing ./launch.sh.
I know this is not a standard solution, but it worked for me. Hopefully it will help you too. If you have any problems or tips to improve, please share with us.
回答2:
You can always create a simple Java class that starts Gatling with the Gatling.fromArgs. With this setup you can have all in just one happy executable jar. Let this class be the jar mainClass instead of "io.gatling.app.Gatling". This example is for a scala simulation class "my.package.MySimulation".
import scala.Option;
import io.gatling.app.Gatling;
import io.gatling.core.scenario.Simulation;
public class StartSimulation {
public static void main(String[] args) {
Gatling.fromArgs(new String[]{}, new Option<Class<Simulation>>() {
private static final long serialVersionUID = 1L;
@Override
public int productArity() {
return 0;
}
@Override
public Object productElement(int arg0) {
return null;
}
@SuppressWarnings("unchecked")
@Override
public Class<Simulation> get() {
try {
return (Class<Simulation>) Class.forName("my.package.MySimulation");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean canEqual(Object o) {
return false;
}
});
}
}
回答3:
I think is a bit late for that but I face kinda the same problem related here, but instead to use maven I used gradle. Guess that the approach it's the same, a bit mix of the first solution and something or my own.
First, define a gradle build file with gatling dependencies and a task to build a fatjar
apply plugin: 'scala'
version 0.1
dependencies {
compile group: 'io.gatling', name: 'gatling-test-framework', version: '2.1.7'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.4.7'
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.7'
}
repositories{
mavenCentral()
mavenLocal()
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Preparing test',
'Implementation-Version': version,
'Main-Class': 'io.gatling.app.Gatling'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } {
exclude 'META-INF/MANIFEST.MF'
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
}
with jar
}
That task executed as
gradle clean build fatJar
will generate a self contained jar which will run the Gatling main class as default. So tell it witch test you want to run is made with the standard '-s' parameter.
So last step is create, if you want, a script to run it. I will "steal" the script for the first comment and change a bit
#!/bin/sh
if [ -z "$1" ];
then
echo "Test config tool"
echo
echo "Running Parameters : "
echo
echo " <Config file> : Test definition file. Required"
echo
exit 0;
fi
USER_ARGS="-DCONFIG_FILE=$1"
JAVA_OPTS="-server -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -Xms512M -Xmx2048M -XX:+HeapDumpOnOutOfMemoryError -XX:+AggressiveOpts -XX:+OptimizeStringConcat -XX:+UseFastAccessorMethods -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false ${JAVA_OPTS}"
java $JAVA_OPTS $USER_ARGS -jar test-project-all-0.1.jar -s FunctionalTestSimulation -nr
In my case I will run the same test with different, easy to configure, parameters so my Simulation is always the same. All my scala files are compiled by gradle and package in the jar that's mean they are in the classpath, changing the "FunctionalTestSimulation" name for a Script variable make easy adapt this script for something more generic.
Guess that make a Maven version will be easy.
Hope that help somebody.
Update with folder structure After a request will add an small draft of the folder structure for the project:
test-project
|_ build.gradle
|_ src
|_ main
|_ scala
|_ resources
|_ runSimulation.sh
|_ configFile.conf
When have time will provide a link to my github with a working one. Cheers
回答4:
I had a similar issue, I fixed it as following:
Inside Gatling package there is bin/
and take a look at gatling.sh
. You see that it simply adds certain configurations into classpath and then runs io.gatling.app.Gatling
class in gatling-compiler-<version_number>.jar
. So, all you need to do is to make a jar that includes compiler, add configurations and tests to classpath and run io.gatling.app.Gatling
.
steps:
add compiler dependency:
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-compiler</artifactId>
<version>${gatling.version}</version>
</dependency
create jar with dependencies:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
create test jar (this includes your gatling tests)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
<configuration>
<excludes>
<exclude>src/test/resources/*</exclude>
</excludes>
<finalName>${project.build.finalName}</finalName>
</configuration>
</execution>
</executions>
</plugin>
create a package out of your configuration. You can use maven assembly for that. What I usually do, is to create a separate module that handles creating the package for different environments. This package contains your gatling.conf
, logback.xml
and all the other resources you application wants including test data.
Now you basically have three packages: application.jar
, application-tests.jar
and application-conf.zip
.
Unzip application-conf.zip
, copy application.jar
and application-tests.jar
in the same folder.
In this folder, You need to create target/test-classes/
folder, just
leave it empty. In my case, it was required. I think you can some how
change that in gatling.conf
. But I am not sure how.
Run
java -cp ".:application-test.jar:application.jar" io.gatling.app.Gatling
回答5:
I use IntelliJ Idea and I got this fixed by right clicking on the scala folder > Mark Directory as > Test Sources Root . Now Execute "Engine" and you will be all good !
回答6:
I've recently blogged about this Creating a versionable, self-contained (fat-/uber-) JAR for Gatling tests, the source of which can be found in jamietanna/fat-gatling-jar.
For a Maven project, the steps would be as follows.
The main things you need are to add the dependency on gatling-charts-highcharts
:
<project>
<!-- ... -->
<dependencies>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>${gatling.version}</version>
</dependency>
</dependencies>
</project>
Next, you need to make sure your Gatling scenarios/simulations are in src/main
instead of src/test
.
Finally, you can use the maven-shade-plugin
to build an executable JAR which uses Gatling's CLI runner as the mainClass
:
<project>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<filters>
<!-- https://stackoverflow.com/a/6743609 -->
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.gatling.app.Gatling</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
来源:https://stackoverflow.com/questions/27893423/build-executable-jar-for-gatling-load-test