Load Generator Framework

Theodolite’s benchmarks come with a flexible load generator framework. It is used to create load on the 4 Theodolite benchmarks, but can also be applied to create custom load generators. It is particularly designed for scalability: Just spin up multiple instances of the load generator and the instances automatically divide the load to be generated among themselves.

Prebuilt container images

For each benchmark, we provide a load generator as OCI container image. These load generators simulate smart power meters in an industrial facility, which generate measurement records at a fixed rate. Records are published to an Apache Kafka topic (default) or sent as POST requests to an HTTP endpoint.

You can simply run a load generator container, for example, for benchmark UC1 with:

docker run -it ghcr.io/cau-se/theodolite-uc1-workload-generator

Message format

Messages generated by the load generators represent a single measurement of active power. The corresponding message type is specified as ActivePowerRecords defined with Avro. It consists of an identifier for simulated power sensor, a timestamp in epoch milliseconds and the actual measured (simulated) value in watts.

When sending generated records via Apache Kafka, these records are serialized with the Confluent Schema Registry. If the load generator is configured to send records as HTTP POST requests, records are serialized as JSON according to the following format:

{
  "identifier": "sensor-id",
  "timestamp": 1645564942000,
  "valueInW": 1234.56
}

Configuration

The prebuilt container images can be configured with the following environment variables:

Environment Variable Description Default
BOOTSTRAP_SERVER Address (hostname:port) of another load generator instance to form a cluster with. Can also be this instance. localhost:5701
KUBERNETES_DNS_NAME Kubernetes service name to discover other load generators to form a cluster with. Must be a fully qualified domain name (FQDN), e.g., something like <service>.<namespace>.svc.cluster.local. Requires BOOTSTRAP_SERVER not to be set.  
PORT Port used for for coordination among load generator instances. 5701
PORT_AUTO_INCREMENT If set to true and the specified PORT is already used, use the next higher one. Useful if multiple instances should run on the same host, without configuring each instance individually. true
CLUSTER_NAME_PREFIX Only required if unrelated load generators form a cluster. theodolite-load-generation
TARGET The target system the load generator send messages to. Valid values are: kafka, http and pubsub. kafka
KAFKA_BOOTSTRAP_SERVERS A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. See Kafka producer config: bootstrap.servers for more information. Only used if Kafka is set as TARGET. localhost:9092
KAFKA_INPUT_TOPIC Name of the Kafka topic, which should receive the generated messages. Only used if Kafka is set as TARGET. input
SCHEMA_REGISTRY_URL URL of the Confluent Schema Registry. http://localhost:8081
KAFKA_BATCH_SIZE Value for the Kafka producer configuration: batch.size. Only used if Kafka is set as TARGET. see Kafka producer config: batch.size
KAFKA_LINGER_MS Value for the Kafka producer configuration: linger.ms. Only used if Kafka is set as TARGET. see Kafka producer config: linger.ms
KAFKA_BUFFER_MEMORY Value for the Kafka producer configuration: buffer.memory Only used if Kafka is set as TARGET. see Kafka producer config: buffer.memory
HTTP_URL The URL the load generator should post messages to. Only used if HTTP is set as TARGET.  
HTTP_ASYNC Whether the load generator should send HTTP messages asynchronously. Only used if HTTP is set as TARGET. false
HTTP_TIMEOUT_MS Timeout in milliseconds for sending HTTP messages. Only used if HTTP is set as TARGET. 1000
PUBSUB_INPUT_TOPIC The Google Cloud Pub/Sub topic to write messages to. Only used if Pub/Sub is set as TARGET. input
PUBSUB_PROJECT The Google Cloud this Pub/Sub topic is associated with. Only used if Pub/Sub is set as TARGET.  
PUBSUB_EMULATOR_HOST A Pub/Sub emulator host. Only used if Pub/Sub is set as TARGET.  
NUM_SENSORS The amount of simulated sensors. 10
PERIOD_MS The time in milliseconds between generating two messages for the same sensor. With our Theodolite benchmarks, we apply an open workload model in which new messages are generated at a fixed rate, without considering the think time of the target server nor the time required for generating a message. 1000
VALUE The constant valueInW of an ActivePowerRecord. 10
THREADS Number of worker threads used to generate the load. 4
DISABLE_DNS_CACHING Set to true to disable DNS caching by the underlying JVM. You might want to do so when generating load via HTTP that should be sent to different target instances. false

Please note that there are some additional configuration options for benchmark UC4’s load generator.

Creating a custom load generator

To create a custom load generator, you need to import the load-generator-commons project. You can then create an instance of the LoadGenerator populated with a default configuration, adjust it as desired, and start it by calling its run method:

LoadGenerator loadGenerator = new LoadGenerator.fromDefaults()
    .setClusterConfig(clusterConfig)
    .setLoadDefinition(new WorkloadDefinition(
        new KeySpace(key_prefix, numSensors),
        duration))
    .setGeneratorConfig(new LoadGeneratorConfig(
        recordGenerator,
        recordSender))
    .withThreads(threads);
loadGenerator.run();

Alternatively, you can also start with a LoadGenerator created from environment variables and, optionally, adjust it as desired:

LoadGenerator loadGenerator = LoadGenerator.fromEnvironment();