pekko/akka-cluster/src/multi-jvm/scala/akka/cluster/LargeMessageClusterSpec.scala
kerr bdc90052aa Update headers from 2018 to 2019 once for all. (#26165)
* Add CopyrightHeader support for sbt-boilerplate plugin.
* Add CopyrightHeader support for `*.proto` files.
* Add regex match for both `–` and `-` for CopyrightHeader.
* Add CopyrightHeader support for sbt build files.
* Update copyright from 2018 to 2019.
2019-01-02 11:55:26 +01:00

175 lines
5.6 KiB
Scala

/*
* Copyright (C) 2017-2019 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.cluster
import scala.concurrent.duration._
import akka.actor.ActorIdentity
import akka.actor.ActorRef
import akka.actor.ExtendedActorSystem
import akka.actor.Identify
import akka.cluster.ClusterEvent.UnreachableMember
import akka.remote.artery.ArterySettings
import akka.remote.testconductor.RoleName
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.serialization.SerializerWithStringManifest
import akka.testkit._
import com.typesafe.config.ConfigFactory
object LargeMessageClusterMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
val second = role("second")
val third = role("third")
// Note that this test uses default configuration,
// not MultiNodeClusterSpec.clusterConfig
commonConfig(ConfigFactory.parseString(
s"""
akka {
cluster.debug.verbose-heartbeat-logging = on
loggers = ["akka.testkit.TestEventListener"]
actor {
provider = cluster
serializers {
test = "akka.cluster.LargeMessageClusterMultiJvmSpec$$SlowSerializer"
}
serialization-bindings {
"akka.cluster.LargeMessageClusterMultiJvmSpec$$Slow" = test
}
}
testconductor.barrier-timeout = 3 minutes
cluster.failure-detector.acceptable-heartbeat-pause = 5 s
remote.artery {
enabled = on
large-message-destinations = [ "/user/largeEcho", "/system/largeEchoProbe-3" ]
advanced {
maximum-large-frame-size = 2 MiB
large-buffer-pool-size = 32
}
}
}
"""))
final case class Slow(payload: Array[Byte])
class SlowSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest {
override def identifier = 999
override def manifest(o: AnyRef) = "a"
override def toBinary(o: AnyRef) = o match {
case Slow(payload)
// simulate slow serialization to not completely overload the machine/network, see issue #24576
Thread.sleep(100)
payload
}
override def fromBinary(bytes: Array[Byte], manifest: String) = {
Slow(bytes)
}
}
}
class LargeMessageClusterMultiJvmNode1 extends LargeMessageClusterSpec
class LargeMessageClusterMultiJvmNode2 extends LargeMessageClusterSpec
class LargeMessageClusterMultiJvmNode3 extends LargeMessageClusterSpec
abstract class LargeMessageClusterSpec extends MultiNodeSpec(LargeMessageClusterMultiJvmSpec)
with MultiNodeClusterSpec with ImplicitSender {
import LargeMessageClusterMultiJvmSpec._
override def expectedTestDuration: FiniteDuration = 3.minutes
def identify(role: RoleName, actorName: String): ActorRef = within(10.seconds) {
system.actorSelection(node(role) / "user" / actorName) ! Identify(actorName)
expectMsgType[ActorIdentity].ref.get
}
val unreachableProbe = TestProbe()
"Artery Cluster with large messages" must {
"init cluster" taggedAs LongRunningTest in {
Cluster(system).subscribe(unreachableProbe.ref, ClusterEvent.InitialStateAsEvents,
classOf[UnreachableMember])
awaitClusterUp(first, second, third)
// let heartbeat monitoring begin
unreachableProbe.expectNoMessage(5.seconds)
enterBarrier("init-done")
}
"not disturb cluster heartbeat messages when sent in bursts" taggedAs LongRunningTest in {
runOn(second, third) {
system.actorOf(TestActors.echoActorProps, "echo")
system.actorOf(TestActors.echoActorProps, "largeEcho")
}
enterBarrier("actors-started")
runOn(second) {
val echo3 = identify(third, "echo")
val largeEcho3 = identify(third, "largeEcho")
val largeEchoProbe = TestProbe(name = "largeEchoProbe")
val largeMsgSize = 2 * 1000 * 1000
val largeMsg = ("0" * largeMsgSize).getBytes("utf-8")
val largeMsgBurst = 3
val repeat = 15
for (n 1 to repeat) {
val startTime = System.nanoTime()
for (_ 1 to largeMsgBurst) {
largeEcho3.tell(largeMsg, largeEchoProbe.ref)
}
val ordinaryProbe = TestProbe()
echo3.tell(("0" * 1000).getBytes("utf-8"), ordinaryProbe.ref)
ordinaryProbe.expectMsgType[Array[Byte]]
val ordinaryDurationMs = (System.nanoTime() - startTime) / 1000 / 1000
largeEchoProbe.receiveN(largeMsgBurst, 20.seconds)
println(s"Burst $n took ${(System.nanoTime() - startTime) / 1000 / 1000} ms, ordinary $ordinaryDurationMs ms")
}
}
enterBarrier("sending-complete-1")
unreachableProbe.expectNoMessage(1.seconds)
enterBarrier("after-1")
}
"not disturb cluster heartbeat messages when saturated" taggedAs LongRunningTest in {
// for non Aeron transport we use the Slow message and SlowSerializer to slow down
// to not completely overload the machine/network, see issue #24576
val arterySettings = ArterySettings(system.settings.config.getConfig("akka.remote.artery"))
val aeronUdpEnabled = (arterySettings.Enabled && arterySettings.Transport == ArterySettings.AeronUpd)
runOn(second) {
val largeEcho2 = identify(second, "largeEcho")
val largeEcho3 = identify(third, "largeEcho")
val largeMsgSize = 1 * 1000 * 1000
val payload = ("0" * largeMsgSize).getBytes("utf-8")
val largeMsg = if (aeronUdpEnabled) payload else Slow(payload)
(1 to 3).foreach { _
// this will ping-pong between second and third
largeEcho2.tell(largeMsg, largeEcho3)
}
}
unreachableProbe.expectNoMessage(10.seconds)
enterBarrier("after-2")
}
}
}