Skip to content

Commit

Permalink
Improve Simulation Tools and Add Documentation (apache#328)
Browse files Browse the repository at this point in the history
* Add documentation, improve simulation tools.

* Add global summary for monitor

* monitor -> monitor-brokers

* Don't modify performance producer/consumer

* Use property/cluster instead of cluster/property for simulation

* Fix regex
  • Loading branch information
bobbeyreese authored and merlimat committed Apr 6, 2017
1 parent 8080e88 commit b38da88
Show file tree
Hide file tree
Showing 13 changed files with 1,149 additions and 796 deletions.
17 changes: 7 additions & 10 deletions bin/pulsar-perf
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,11 @@ pulsar_help() {
cat <<EOF
Usage: pulsar <command>
where command is one of:
produce Run a producer
consume Run a consumer
monitor-simple-load-manager Continuously receive broker data when using SimpleLoadManagerImpl
monitor-modular-load-manager Continuously receive broker data when using ModularLoadManagerImpl
simulation-client Run a simulation server acting as a Pulsar client
simulation-controller Run a simulation controller to give commands to servers
produce Run a producer
consume Run a consumer
monitor-brokers Continuously receive broker data and/or load reports
simulation-client Run a simulation server acting as a Pulsar client
simulation-controller Run a simulation controller to give commands to servers
help This help message
Expand Down Expand Up @@ -142,10 +141,8 @@ if [ "$COMMAND" == "produce" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.PerformanceProducer --conf-file $PULSAR_PERFTEST_CONF "$@"
elif [ "$COMMAND" == "consume" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.PerformanceConsumer --conf-file $PULSAR_PERFTEST_CONF "$@"
elif [ "$COMMAND" == "monitor-simple-load-manager" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.SimpleLoadManagerBrokerMonitor "$@"
elif [ "$COMMAND" == "monitor-modular-load-manager" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.ModularLoadManagerBrokerMonitor "$@"
elif [ "$COMMAND" == "monitor-brokers" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.BrokerMonitor "$@"
elif [ "$COMMAND" == "simulation-client" ]; then
exec $JAVA $OPTS com.yahoo.pulsar.testclient.LoadSimulationClient "$@"
elif [ "$COMMAND" == "simulation-controller" ]; then
Expand Down
1 change: 1 addition & 0 deletions docs/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [Apache Storm adaptor](PulsarStorm.md)
- [Spark Streaming Pulsar Receiver](PulsarSpark.md)
- [Modular Load Manager](ModularLoadManager.md)
- [Simulation Tools](Simulation.md)
* Internal Docs
- [Binary protocol specification](BinaryProtocol.md)
* Other Languages
Expand Down
101 changes: 101 additions & 0 deletions docs/SimulationTools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Simulation Tools

It is sometimes necessary create an test environment and incur artificial load to observe how well load managers
handle the load. The load simulation controller, the load simulation client, and the broker monitor were created as an
effort to make create this load and observe the effects on the managers more easily.

## Simulation Client
The simulation client is a machine which will create and subscribe to topics with configurable message rates and sizes.
Because it is sometimes necessary in simulating large load to use multiple client machines, the user does not interact
with the simulation client directly, but instead delegates their requests to the simulation controller, which will then
send signals to clients to start incurring load. The client implementation is in the class
`com.yahoo.pulsar.testclient.LoadSimulationClient`.

### Usage
To Start a simulation client, use the `pulsar-perf` script with the command `simulation-client` as follows:

```
pulsar-perf simulation-client --port <listen port> --service-url <pulsar service url>
```

The client will then be ready to receive controller commands.
## Simulation Controller
The simulation controller send signals to the simulation clients, requesting them to create new topics, stop old
topics, change the load incurred by topics, as well as several other tasks. It is implemented in the class
`com.yahoo.pulsar.testclient.LoadSimulationController` and presents a shell to the user as an interface to send
command with.

### Usage
To start a simulation controller, use the `pulsar-perf` script with the command `simulation-controller` as follows:

```
pulsar-perf simulation-controller --cluster <cluster to simulate on> --client-port <listen port for clients>
--clients <comma-separated list of client host names>
```

The clients should already be started before the controller is started. You will then be presented with a simple prompt,
where you can issue commands to simulation clients. Arguments often refer to tenant names, namespace names, and topic
names. In all cases, the BASE name of the tenants, namespaces, and topics are used. For example, for the topic
`persistent://my_cluster/my_tenant/my_namespace/my_topic`, the tenant name is `my_tenant`, the namespace name is
`my_namespace`, and the topic name is `my_topic`. The controller can perform the following actions:

* Create a topic with a producer and a consumer
* `trade <tenant> <namespace> <topic> [--rate <message rate per second>]
[--rand-rate <lower bound>,<upper bound>]
[--size <message size in bytes>]`
* Create a group of topics with a producer and a consumer
* `trade_group <tenant> <group> <num_namespaces> [--rate <message rate per second>]
[--rand-rate <lower bound>,<upper bound>]
[--separation <separation between creating topics in ms>] [--size <message size in bytes>]
[--topics-per-namespace <number of topics to create per namespace>]`
* Change the configuration of an existing topic
* `change <tenant> <namespace> <topic> [--rate <message rate per second>]
[--rand-rate <lower bound>,<upper bound>]
[--size <message size in bytes>]`
* Change the configuration of a group of topics
* `change_group <tenant> <group> [--rate <message rate per second>] [--rand-rate <lower bound>,<upper bound>]
[--size <message size in bytes>] [--topics-per-namespace <number of topics to create per namespace>]`
* Shutdown a previously created topic
* `stop <tenant> <namespace> <topic>`
* Shutdown a previously created group of topics
* `stop_group <tenant> <group>`
* Copy the historical data from one ZooKeeper to another and simulate based on the message rates and sizes in that
history
* `copy <tenant> <source zookeeper> <target zookeeper> [--rate-multiplier value]`
* Simulate the load of the historical data on the current ZooKeeper (should be same ZooKeeper being simulated on)
* `simulate <tenant> <zookeeper> [--rate-multiplier value]`
* Stream the latest data from the given active ZooKeeper to simulate the real-time load of that ZooKeeper.
* `stream <tenant> <zookeeper> [--rate-multiplier value]`

The "group" arguments in these commands allow the user to create or affect multiple topics at once. Groups are created
when calling the `trade_group` command, and all topics from these groups may be subsequently modified or stopped
with the `change_group` and `stop_group` commands respectively. All ZooKeeper arguments are of the form
`zookeeper_host:port`.

#### Difference Between Copy, Simulate, and Stream
The commands `copy`, `simulate`, and `stream` are very similar but have significant differences. `copy` is used when
you want to simulate the load of a static, external ZooKeeper on the ZooKeeper you are simulating on. Thus,
`source zookeeper` should be the ZooKeeper you want to copy and `target zookeeper` should be the ZooKeeper you are
simulating on, and then it will get the full benefit of the historical data of the source in both load manager
implementations. `simulate` on the other hand takes in only one ZooKeeper, the one you are simulating on. It assumes
that you are simulating on a ZooKeeper that has historical data for `SimpleLoadManagerImpl` and creates equivalent
historical data for `ModularLoadManagerImpl`. Then, the load according to the historical data is simulated by the
clients. Finally, `stream` takes in an active ZooKeeper different than the ZooKeeper being simulated on and streams
load data from it and simulates the real-time load. In all cases, the optional `rate-multiplier` argument allows the
user to simulate some proportion of the load. For instance, using `--rate-multiplier 0.05` will cause messages to
be sent at only `5%` of the rate of the load that is being simulated.

## Broker Monitor
To observe the behavior of the load manager in these simulations, one may utilize the broker monitor, which is
implemented in `com.yahoo.pulsar.testclient.BrokerMonitor`. The broker monitor will print tabular load data to the
console as it is updated using watchers.

### Usage
To start a broker monitor, use the `monitor-brokers` command in the `pulsar-perf` script:

```
pulsar-perf monitor-brokers --connect-string <zookeeper host:port>
```

The console will then continuously print load data until it is interrupted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yahoo.pulsar.broker.PulsarServerException;
import com.yahoo.pulsar.broker.PulsarService;
import com.yahoo.pulsar.broker.ServiceConfiguration;
Expand All @@ -25,8 +28,6 @@
import com.yahoo.pulsar.broker.stats.Metrics;
import com.yahoo.pulsar.common.naming.ServiceUnitId;
import com.yahoo.pulsar.common.policies.data.loadbalancer.LoadReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* LoadManager runs though set of load reports collected from different brokers and generates a recommendation of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@
*/
package com.yahoo.pulsar.broker.loadbalance.impl;

import com.yahoo.pulsar.broker.loadbalance.BrokerHostUsage;
import com.yahoo.pulsar.common.naming.NamespaceName;
import com.yahoo.pulsar.common.naming.ServiceUnitId;
import com.yahoo.pulsar.common.policies.data.loadbalancer.SystemResourceUsage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkArgument;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yahoo.pulsar.broker.loadbalance.BrokerHostUsage;
import com.yahoo.pulsar.common.naming.NamespaceName;
import com.yahoo.pulsar.common.naming.ServiceUnitId;
import com.yahoo.pulsar.common.policies.data.loadbalancer.SystemResourceUsage;

/**
* This class contains code which in shared between the two load manager implementations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
*/
package com.yahoo.pulsar.broker.loadbalance.impl;

import static com.google.common.base.Preconditions.checkArgument;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
Expand All @@ -31,9 +28,6 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.yahoo.pulsar.broker.TimeAverageMessageData;
import com.yahoo.pulsar.broker.loadbalance.LoadManager;
import com.yahoo.pulsar.common.policies.data.ResourceQuota;
import org.apache.bookkeeper.util.ZkUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
Expand All @@ -57,14 +51,17 @@
import com.yahoo.pulsar.broker.PulsarService;
import com.yahoo.pulsar.broker.ServiceConfiguration;
import com.yahoo.pulsar.broker.TimeAverageBrokerData;
import com.yahoo.pulsar.broker.TimeAverageMessageData;
import com.yahoo.pulsar.broker.loadbalance.BrokerFilter;
import com.yahoo.pulsar.broker.loadbalance.BrokerHostUsage;
import com.yahoo.pulsar.broker.loadbalance.LoadData;
import com.yahoo.pulsar.broker.loadbalance.LoadManager;
import com.yahoo.pulsar.broker.loadbalance.LoadSheddingStrategy;
import com.yahoo.pulsar.broker.loadbalance.ModularLoadManager;
import com.yahoo.pulsar.broker.loadbalance.ModularLoadManagerStrategy;
import com.yahoo.pulsar.client.admin.PulsarAdmin;
import com.yahoo.pulsar.common.naming.ServiceUnitId;
import com.yahoo.pulsar.common.policies.data.ResourceQuota;
import com.yahoo.pulsar.common.policies.data.loadbalancer.NamespaceBundleStats;
import com.yahoo.pulsar.common.policies.data.loadbalancer.SystemResourceUsage;
import com.yahoo.pulsar.common.util.ObjectMapperFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
*/
package com.yahoo.pulsar.broker.loadbalance.impl;

import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
Expand Down
Loading

0 comments on commit b38da88

Please sign in to comment.