Home

Awesome

Swarm

An elegant Java client for Locust

1. Motivation

IMHO, Locust4j a basic implementation for Locust clients written in Java. It has so many restrictions, including:

Based on implementation of Locust4j, Swarm is completely re-written to address all issues above, with some additional features:

2. Implementation

3. Installation

Before using Swarm, you must declare it as a dependency of your Maven project. For example:

<dependency>
    <groupId>com.bigsonata.swarm</groupId>
    <artifactId>locust-swarm</artifactId>
    <version>1.1.6</version>
</dependency>

You also have to add following dependencies:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.3</version>
</dependency>

<dependency>
    <groupId>org.msgpack</groupId>
    <artifactId>msgpack-core</artifactId>
    <version>0.8.13</version>
</dependency>

<dependency>
    <groupId>org.zeromq</groupId>
    <artifactId>jeromq</artifactId>
    <version>0.4.3</version>
</dependency>

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.7</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>23.0</version>
</dependency>

4. How to write your benchmarks

4.1 Overview

Swarm uses the term of Cron to refer to repeating tasks defined by you.

Life cycle of a Cron-based instance can be described in the following diagram:

Swarm is responsible for cloning, initializing crons.

4.2 Cron anatomy
// Here is an abridged version of class Cron
public abstract class Cron implements Cloneable, Runnable {
  public Cron(Props props) {
    this.props = props;
  }

  public abstract void process();

  public abstract Cron clone();

  public void recordFailure(long responseTime, String error) {
    // ..
  }

  public void recordSuccess(long responseTime, long contentLength) {
    // ..
  }

  public void recordSuccess(long responseTime) {
    // ..
  }

  @Override
  public void run() {
    // ...
    process();
  }

  public abstract void dispose();

  public abstract void initialize();
}

Each cron has its own props which defines type & name (to display on the Web interface):

public class Props {
  protected String type = "default";
  protected String name = "cron";
  protected int weight = 1;
  protected boolean async = false;

  public static Props create() {
    return new Props();
  }

  public static Props createAsync() {
    return new Props()
        .setAsync(true);
  }


  public Props setType(String type) {
    // ..
  }

  public Props setName(String name) {
    // ..
  }

  public Props setWeight(int weight) {
    // ..
  }

  public Props setAsync(boolean async) {
    // ..
  }
}

NOTE: A cron must specify how it works: synchronously or asynchronously

Inside each cron, there are 4 must-overridden methods

4.3 Define your crons

You need to define your loading test by deriving class Cron:

For example, in our AsyncCron:

public class TimerCron extends Cron {
  public TimerCron() {
    super(Props.create().setName("timer").setAsync(false));
  }

  @Override
  public void process() {
    try {
      System.out.println("> Processing...");
      long start = System.currentTimeMillis();
      Thread.sleep(1000);
      long duration = System.currentTimeMillis() - start;
      recordSuccess(duration);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  @Override
  public Cron clone() {
    return new TimerCron();
  }

  @Override
  public void dispose() {
  }

  @Override
  public void initialize() {
  }
}
4.4 Finalize

After defining your crons, finally you need to instruct Swarm to start:

Locust.Builder.newInstance()
    .setMasterHost(masterHost)
    .setMasterPort(masterPort)

    // Optionally set the interval (in ms) to report statistics
    // Default: 2000
    .setStatInterval(2000)

    // Optionally set a seed number to generate nodeId
    .setRandomSeed(0)

    // Optionally set the number of threads to stimulate Crons
    // Default: 8
    .setThreads(8)

    // Optionally set the number of maximum requests per second
    .setMaxRps(1000)

    // Register cron tasks
    .setCrons(new TimerCron());
    .build()

5. Tips

6. Contributions

If you find anything wrong or would like to contribute in any way, feel free to create a pull request/open an issue/send me a message. Any comments are welcome!

<a href="https://github.com/anhldbk/swarm/graphs/contributors"> <img src="https://contrib.rocks/image?repo=anhldbk/swarm" /> </a>

7. History

v1.1.6

v1.1.5

v1.1.4

v1.1.3

v1.1.0

v1.0.1

v1.0.0

v0.1.2

v0.1.0