【问题标题】:Build executable JAR for Gatling load test为 Gatling 负载测试构建可执行 JAR
【发布时间】:2018-11-22 05:10:58
【问题描述】:

我是 Gatling (2.1.2) 的新手,想做一个小型原型项目展示给我的同事。

根据quick start 页面,我可以通过多种方式使用 Gatling 运行模拟:

  1. 将 Gatling 包解压到一个文件夹中,然后将我的模拟文件放到 user-files/simulations 文件夹中。 bin/gatling.sh 将编译并运行模拟文件。
  2. 使用gatling-maven-plugin maven 插件来执行模拟。
  3. 使用gatling-highcharts-maven-archetype 创建一个项目,然后运行Engine 类。

我发现了这些问题

对于 1,很难为模拟类添加依赖项。我必须弄清楚需要什么 jar 并将它们放到 lib 文件夹中。

对于2,需要安装maven。

对于 3,它只能从 IDE 运行

我只想要一个简单的可执行 JAR 文件,其中包含捆绑在一起的所有依赖项(我的模拟、Gatling 和第三方),并从任何机器(如 EC2 实例)运行它。

有没有办法做到这一点?

更新 1:

我尝试了方法3,但是将所有项目文件从test文件夹移动到main,并使用maven-assembly-plugin构建了一个带有依赖项的jar。当我尝试运行该文件时,出现以下错误:

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

我猜这与 Gatling 配置有关,但不知道出了什么问题。

【问题讨论】:

  • 如果你想构建一个 PoC,为什么不首先坚持官方支持的部署策略呢?
  • @StephaneLandelle,我实际上已经尝试过官方策略,这就是我发现我必须将所有 jar 放入 lib 文件夹的原因。我只是想知道是否可以构建一个可运行的 JAR,以及为什么。
  • @Philippe,您也许可以在我的问题中使用方法 1。您需要做的是解压缩 Gatling bundle zip 文件,并将您的场景 scala 文件粘贴到 ${GATLING}/user-files/simulations 文件夹中。任何依赖的 jar 都应该进入 ${GATLING}/lib (如果它不在包中,则需要创建文件夹)。然后你可以通过 ${GATLING}/bin/gatlin.sh 运行 Gatling。 file 告诉你它是如何工作的。
  • 这是目前最好的做法,直到 Gatling 提供了一个独立的可运行文件,这正是我想要的。

标签: java load-testing gatling


【解决方案1】:

我尝试做类似的事情。我也不能使用 Maven。我会尽量记住我是怎么做到的。

1) 我已将 ma​​ven-assembly-plugin 配置为生成具有如下依赖项的单个 JAR:

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>

您需要确保生成的类路径中存在所有必需的库(gatling、scala 运行时、zinc 编译器)。

2) 检查依赖项的范围,因为 Maven 默认只打包使用 scope=compile 定义的类。最简单的方法可能是不使用测试依赖项。

3) 创建一个启动脚本,例如launch.sh。它应该包含如下内容:

#!/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

为了解释,我以 gatling 自己的启动脚本作为灵感。主要注意类路径参数定义中 target 目录的存在。

4) 将您编译的 target 目录和 launch.sh 编译到单个目录并分发(例如作为存档)。然后你可以通过执行 ./launch.sh.

我知道这不是标准解决方案,但它对我有用。希望它也会对您有所帮助。如果您有任何问题或需要改进的提示,请与我们分享。

【讨论】:

  • 抱歉回复晚了。这和我最终做的几乎一样。希望加特林团队对此给予官方支持。
  • 如何指定模拟类列表? -sf 不起作用,因为它需要文件夹路径而不是捆绑 jar 中的包路径
【解决方案2】:

我认为这有点晚了,但我在这里遇到了同样的问题,但是为了使用 Maven,我使用了 gradle。猜猜方法是一样的,有点混合了第一个解决方案和我自己的东西。

首先,定义一个带有 gatling 依赖项的 gradle 构建文件和一个构建 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
}

该任务执行为

gradle clean build fatJar

将生成一个自包含的 jar,它将默认运行 Gatling 主类。所以告诉它你要运行的女巫测试是使用标准的“-s”参数进行的。

所以最后一步是根据需要创建一个脚本来运行它。我将“窃取”第一条评论的脚本并稍作改动

#!/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

在我的情况下,我将使用不同的、易于配置的参数运行相同的测试,因此我的模拟始终相同。 我所有的 scala 文件都由 gradle 编译并打包在 jar 中,这意味着它们位于类路径中,更改脚本变量的“FunctionalTestSimulation”名称可以轻松地调整此脚本以适应更通用的内容。

猜想制作一个 Maven 版本会很容易。

希望对某人有所帮助。

更新文件夹结构 请求后会为项目添加一个文件夹结构的小草稿:

test-project
    |_ build.gradle
    |_ src
        |_ main
            |_ scala
            |_ resources
    |_ runSimulation.sh
    |_ configFile.conf

如果有时间,我会提供一个链接到我的 github 和一个可用的链接。 干杯

【讨论】:

  • 这真的很有帮助,谢谢。一件小事,我看到您在顶部两次以不同的格式导入了 scala-library。你可以删除它
  • 谢谢,没想到!
  • 您能否分享一下适用于这个 Gradle 脚本的项目目录结构?例如你的测试和资源在哪里
  • 是的,我会准备一些示例代码并将其放在我的 github 中。但是需要一些时间,因为那几天我真的很忙。没关系?如果您着急,请给我发电子邮件,我会尽力解释。
  • 要使脚本生成报告删除 -nr 并将 "compile "io.gatling.highcharts:gatling-charts-highcharts:2.3.0"" 添加到 gradle 依赖项中
【解决方案3】:

您始终可以创建一个简单的 Java 类,该类使用 Gatling.fromArgs 启动 Gatling。通过此设置,您可以在一个快乐的可执行 jar 中拥有所有内容。让这个类成为 jar mainClass 而不是“io.gatling.app.Gatling”。此示例适用于 Scala 模拟类“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;
        }
    });
  }
}

【讨论】:

  • 感谢您的回答。问题更多与依赖关系有关。我最终做的是像你一样编写一个自定义的主类,并使用 maven 将项目打包成一个带有依赖项的可执行 JAR。
  • 不幸的是,fromArgs 方法在 2.2.3 版本中被标记为 io.gatling 私有,因此要使用此技巧,您现在需要添加类似:package io.gatling import io.gatling.app。 {Gatling, SelectedSimulationClass} object GatlingHack { def fromArgs(args: Array[String], selectedSimulationClass: SelectedSimulationClass): Int = Gatling.fromArgs(args, selectedSimulationClass) }
  • 请注意,正如 Stephane Landelle 在将 fromArgs 方法设为私有前几天所指出的那样,Gatling 并不意味着以这种方式嵌入:groups.google.com/d/msg/gatling/387pDAweZEY/Va6TsErHAAAJ
【解决方案4】:

我遇到了类似的问题,我将其修复如下:

在 Gatling 包内有 bin/ 并查看 gatling.sh。您会看到它只是将某些配置添加到类路径中,然后在gatling-compiler-&lt;version_number&gt;.jar 中运行io.gatling.app.Gatling 类。因此,您需要做的就是制作一个包含编译器的 jar,将配置和测试添加到类路径并运行 io.gatling.app.Gatling。 步骤:

添加编译器依赖:

<dependency>
        <groupId>io.gatling</groupId>
        <artifactId>gatling-compiler</artifactId>
        <version>${gatling.version}</version>
    </dependency

创建带有依赖项的 jar:

  <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>

创建测试 jar(这包括您的 gatling 测试)

 <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>

根据您的配置创建一个包。您可以为此使用 Maven 程序集。我通常做的是创建一个单独的模块来处理为不同环境创建包。这个包包含你的gatling.conflogback.xml和你应用程序需要的所有其他资源,包括测试数据。 现在你基本上有了三个包:application.jarapplication-tests.jarapplication-conf.zip。 解压application-conf.zip,将application.jarapplication-tests.jar复制到同一个文件夹。

在这个文件夹中,你需要创建target/test-classes/文件夹,只需 留空。就我而言,这是必需的。我想你可以怎么做 在gatling.conf 中更改它。但我不确定如何。

运行

java -cp ".:application-test.jar:application.jar" io.gatling.app.Gatling  

【讨论】:

    【解决方案5】:

    我使用 IntelliJ Idea 并通过右键单击 scala 文件夹 > Mark Directory as > Test Sources Root 解决了这个问题。现在执行“引擎”,一切都会好起来的!

    【讨论】:

    • 如果目录被标记为源根目录,这也有效,而不是测试。我想是快速运行测试的便捷方式。
    【解决方案6】:

    我最近写了一篇关于这个Creating a versionable, self-contained (fat-/uber-) JAR for Gatling tests的博客,其来源可以在jamietanna/fat-gatling-jar找到。

    对于 Maven 项目,步骤如下。

    你需要的主要是添加对gatling-charts-highcharts的依赖:

    <project>
        <!-- ... -->
        <dependencies>
            <dependency>
                <groupId>io.gatling.highcharts</groupId>
                <artifactId>gatling-charts-highcharts</artifactId>
                <version>${gatling.version}</version>
            </dependency>
        </dependencies>
    </project>
    

    接下来,您需要确保您的 Gatling 场景/模拟位于 src/main 而不是 src/test

    最后,您可以使用 maven-shade-plugin 构建一个可执行 JAR,它使用 Gatling 的 CLI 运行器作为 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>  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多