2017-05-10 16:20:38 +02:00
|
|
|
# Multi Node Testing
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## Multi Node Testing Concepts
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2012-09-21 12:30:05 +02:00
|
|
|
When we talk about multi node testing in Akka we mean the process of running coordinated tests on multiple actor
|
|
|
|
|
systems in different JVMs. The multi node testing kit consist of three main parts.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
* [The Test Conductor](#the-test-conductor). that coordinates and controls the nodes under test.
|
|
|
|
|
* [The Multi Node Spec](#the-multi-node-spec). that is a convenience wrapper for starting the `TestConductor` and letting all
|
|
|
|
|
nodes connect to it.
|
|
|
|
|
* [The SbtMultiJvm Plugin](#the-sbtmultijvm-plugin). that starts tests in multiple JVMs possibly on multiple machines.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## The Test Conductor
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
The basis for the multi node testing is the `TestConductor`. It is an Akka Extension that plugs in to the
|
2012-09-20 21:50:35 +02:00
|
|
|
network stack and it is used to coordinate the nodes participating in the test and provides several features
|
|
|
|
|
including:
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
* Node Address Lookup: Finding out the full path to another test node (No need to share configuration between
|
|
|
|
|
test nodes)
|
|
|
|
|
* Node Barrier Coordination: Waiting for other nodes at named barriers.
|
|
|
|
|
* Network Failure Injection: Throttling traffic, dropping packets, unplugging and plugging nodes back in.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
|
|
|
|
This is a schematic overview of the test conductor.
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|

|
2012-09-20 21:50:35 +02:00
|
|
|
|
|
|
|
|
The test conductor server is responsible for coordinating barriers and sending commands to the test conductor
|
2012-10-04 11:03:07 +02:00
|
|
|
clients that act upon them, e.g. throttling network traffic to/from another client. More information on the
|
2017-05-10 16:20:38 +02:00
|
|
|
possible operations is available in the `akka.remote.testconductor.Conductor` API documentation.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## The Multi Node Spec
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
The Multi Node Spec consists of two parts. The `MultiNodeConfig` that is responsible for common
|
|
|
|
|
configuration and enumerating and naming the nodes under test. The `MultiNodeSpec` that contains a number
|
2012-10-04 11:03:07 +02:00
|
|
|
of convenience functions for making the test nodes interact with each other. More information on the possible
|
2017-05-10 16:20:38 +02:00
|
|
|
operations is available in the `akka.remote.testkit.MultiNodeSpec` API documentation.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
The setup of the `MultiNodeSpec` is configured through java system properties that you set on all JVMs that's going to run a
|
|
|
|
|
node under test. These can easily be set on the JVM command line with `-Dproperty=value`.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
|
|
|
|
These are the available properties:
|
2017-05-10 16:20:38 +02:00
|
|
|
:
|
|
|
|
|
*
|
|
|
|
|
`multinode.max-nodes`
|
|
|
|
|
The maximum number of nodes that a test can have.
|
|
|
|
|
*
|
|
|
|
|
`multinode.host`
|
|
|
|
|
The host name or IP for this node. Must be resolvable using InetAddress.getByName.
|
|
|
|
|
*
|
|
|
|
|
`multinode.port`
|
|
|
|
|
The port number for this node. Defaults to 0 which will use a random port.
|
|
|
|
|
*
|
|
|
|
|
`multinode.server-host`
|
|
|
|
|
The host name or IP for the server node. Must be resolvable using InetAddress.getByName.
|
|
|
|
|
*
|
|
|
|
|
`multinode.server-port`
|
|
|
|
|
The port number for the server node. Defaults to 4711.
|
|
|
|
|
*
|
|
|
|
|
`multinode.index`
|
|
|
|
|
The index of this node in the sequence of roles defined for the test. The index 0 is special and that machine
|
|
|
|
|
will be the server. All failure injection and throttling must be done from this node.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## The SbtMultiJvm Plugin
|
|
|
|
|
|
|
|
|
|
The @ref:[SbtMultiJvm Plugin](multi-jvm-testing.md) has been updated to be able to run multi node tests, by
|
|
|
|
|
automatically generating the relevant `multinode.*` properties. This means that you can easily run multi node tests
|
2012-09-21 12:30:05 +02:00
|
|
|
on a single machine without any special configuration by just running them as normal multi-jvm tests. These tests can
|
|
|
|
|
then be run distributed over multiple machines without any changes simply by using the multi-node additions to the
|
|
|
|
|
plugin.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
### Multi Node Specific Additions
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
The plugin also has a number of new `multi-node-*` sbt tasks and settings to support running tests on multiple
|
2012-09-20 21:50:35 +02:00
|
|
|
machines. The necessary test classes and dependencies are packaged for distribution to other machines with
|
2017-05-10 16:20:38 +02:00
|
|
|
[SbtAssembly](https://github.com/sbt/sbt-assembly) into a jar file with a name on the format
|
|
|
|
|
`<projectName>_<scalaVersion>-<projectVersion>-multi-jvm-assembly.jar`
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
@@@ note
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
To be able to distribute and kick off the tests on multiple machines, it is assumed that both host and target
|
|
|
|
|
systems are POSIX like systems with `ssh` and `rsync` available.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
@@@
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
These are the available sbt multi-node settings:
|
|
|
|
|
:
|
|
|
|
|
*
|
|
|
|
|
`multiNodeHosts`
|
|
|
|
|
A sequence of hosts to use for running the test, on the form `user@host:java` where host is the only required
|
|
|
|
|
part. Will override settings from file.
|
|
|
|
|
*
|
|
|
|
|
`multiNodeHostsFileName`
|
|
|
|
|
A file to use for reading in the hosts to use for running the test. One per line on the same format as above.
|
|
|
|
|
Defaults to `multi-node-test.hosts` in the base project directory.
|
|
|
|
|
*
|
|
|
|
|
`multiNodeTargetDirName`
|
|
|
|
|
A name for the directory on the target machine, where to copy the jar file. Defaults to `multi-node-test` in
|
|
|
|
|
the base directory of the ssh user used to rsync the jar file.
|
|
|
|
|
*
|
|
|
|
|
`multiNodeJavaName`
|
|
|
|
|
The name of the default Java executable on the target machines. Defaults to `java`.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
|
|
|
|
Here are some examples of how you define hosts:
|
2017-05-10 16:20:38 +02:00
|
|
|
:
|
|
|
|
|
*
|
|
|
|
|
`localhost`
|
|
|
|
|
The current user on localhost using the default java.
|
|
|
|
|
*
|
|
|
|
|
`user1@host1`
|
|
|
|
|
User `user1` on host `host1` with the default java.
|
|
|
|
|
*
|
|
|
|
|
`user2@host2:/usr/lib/jvm/java-7-openjdk-amd64/bin/java`
|
|
|
|
|
User `user2` on host `host2` using java 7.
|
|
|
|
|
*
|
|
|
|
|
`host3:/usr/lib/jvm/java-6-openjdk-amd64/bin/java`
|
|
|
|
|
The current user on host `host3` using java 6.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Running the Multi Node Tests
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2012-09-21 12:30:05 +02:00
|
|
|
To run all the multi node test in multi-node mode (i.e. distributing the jar files and kicking off the tests
|
2017-05-10 16:20:38 +02:00
|
|
|
remotely) from inside sbt, use the `multi-node-test` task:
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
```none
|
|
|
|
|
multi-node-test
|
|
|
|
|
```
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2012-09-21 12:30:05 +02:00
|
|
|
To run all of them in multi-jvm mode (i.e. all JVMs on the local machine) do:
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
```none
|
|
|
|
|
multi-jvm:test
|
|
|
|
|
```
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
To run individual tests use the `multi-node-test-only` task:
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
```none
|
|
|
|
|
multi-node-test-only your.MultiNodeTest
|
|
|
|
|
```
|
2012-09-21 12:30:05 +02:00
|
|
|
|
|
|
|
|
To run individual tests in the multi-jvm mode do:
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
```none
|
|
|
|
|
multi-jvm:test-only your.MultiNodeTest
|
|
|
|
|
```
|
2012-09-20 21:50:35 +02:00
|
|
|
|
|
|
|
|
More than one test name can be listed to run multiple specific tests. Tab completion in sbt makes it easy to
|
|
|
|
|
complete the test names.
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## Preparing Your Project for Multi Node Testing
|
2012-09-21 12:30:05 +02:00
|
|
|
|
|
|
|
|
The multi node testing kit is a separate jar file. Make sure that you have the following dependency in your project:
|
|
|
|
|
|
2017-05-12 16:07:51 +03:00
|
|
|
@@@vars
|
2017-05-10 16:20:38 +02:00
|
|
|
```
|
2017-05-12 16:07:51 +03:00
|
|
|
"com.typesafe.akka" %% "akka-multi-node-testkit" % $akka.version$
|
|
|
|
|
```
|
|
|
|
|
@@@
|
2012-09-21 12:30:05 +02:00
|
|
|
|
|
|
|
|
If you are using the latest nightly build you should pick a timestamped Akka version from
|
2017-05-12 16:07:51 +03:00
|
|
|
[http://repo.akka.io/snapshots/com/typesafe/akka/akka-multi-node-testkit_2.11/](http://repo.akka.io/snapshots/com/typesafe/akka/akka-multi-node-testkit_2.11/).
|
2017-05-10 16:20:38 +02:00
|
|
|
We recommend against using `SNAPSHOT` in order to obtain stable builds.
|
2012-09-21 12:30:05 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## A Multi Node Testing Example
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
First we need some scaffolding to hook up the `MultiNodeSpec` with your favorite test framework. Lets define a trait
|
|
|
|
|
`STMultiNodeSpec` that uses ScalaTest to start and stop `MultiNodeSpec`.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-11 11:59:28 +03:00
|
|
|
@@snip [STMultiNodeSpec.scala]($akka$/akka-remote-tests/src/test/scala/akka/remote/testkit/STMultiNodeSpec.scala) { #example }
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
Then we need to define a configuration. Lets use two nodes `"node1` and `"node2"` and call it
|
|
|
|
|
`MultiNodeSampleConfig`.
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2017-05-11 11:59:28 +03:00
|
|
|
@@snip [MultiNodeSample.scala]($akka$/akka-remote-tests/src/multi-jvm/scala/akka/remote/sample/MultiNodeSample.scala) { #package #config }
|
2012-09-20 21:50:35 +02:00
|
|
|
|
2012-09-21 12:30:05 +02:00
|
|
|
And then finally to the node test code. That starts the two nodes, and demonstrates a barrier, and a remote actor
|
2012-09-20 21:50:35 +02:00
|
|
|
message send/receive.
|
|
|
|
|
|
2017-05-11 11:59:28 +03:00
|
|
|
@@snip [MultiNodeSample.scala]($akka$/akka-remote-tests/src/multi-jvm/scala/akka/remote/sample/MultiNodeSample.scala) { #package #spec }
|
2012-09-21 12:30:05 +02:00
|
|
|
|
2017-03-31 13:52:05 +03:00
|
|
|
The easiest way to run this example yourself is to download the ready to run
|
2017-05-12 16:07:51 +03:00
|
|
|
@extref[Akka Multi-Node Testing Sample with Scala](ecs:akka-samples-multi-node-scala)
|
|
|
|
|
together with the tutorial. The source code of this sample can be found in the @extref[Akka Samples Repository](samples:akka-sample-multi-node-scala).
|
2014-02-11 13:28:22 +01:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## Things to Keep in Mind
|
2012-09-21 12:30:05 +02:00
|
|
|
|
|
|
|
|
There are a couple of things to keep in mind when writing multi node tests or else your tests might behave in
|
|
|
|
|
surprising ways.
|
|
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
>
|
|
|
|
|
* Don't issue a shutdown of the first node. The first node is the controller and if it shuts down your test will break.
|
|
|
|
|
* To be able to use `blackhole`, `passThrough`, and `throttle` you must activate the failure injector and
|
|
|
|
|
throttler transport adapters by specifying `testTransport(on = true)` in your MultiNodeConfig.
|
|
|
|
|
* Throttling, shutdown and other failure injections can only be done from the first node, which again is the controller.
|
|
|
|
|
* Don't ask for the address of a node using `node(address)` after the node has been shut down. Grab the address before
|
|
|
|
|
shutting down the node.
|
|
|
|
|
* Don't use MultiNodeSpec methods like address lookup, barrier entry et.c. from other threads than the main test
|
|
|
|
|
thread. This also means that you shouldn't use them from inside an actor, a future, or a scheduled task.
|
2012-09-21 12:30:05 +02:00
|
|
|
|
2017-05-10 16:20:38 +02:00
|
|
|
## Configuration
|
2014-03-23 18:39:55 +01:00
|
|
|
|
|
|
|
|
There are several configuration properties for the Multi-Node Testing module, please refer
|
2017-05-11 13:59:29 +02:00
|
|
|
to the @ref:[reference configuration](general/configuration.md#config-akka-multi-node-testkit).
|