2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2018-01-04 17:26:29 +00:00
|
|
|
* Copyright (C) 2009-2018 Lightbend Inc. <https://www.lightbend.com>
|
2012-05-29 08:28:54 +02:00
|
|
|
*/
|
2018-04-24 16:03:55 +01:00
|
|
|
|
2013-09-19 08:00:05 +02:00
|
|
|
package akka.remote.routing
|
2012-07-26 14:47:21 +02:00
|
|
|
|
2013-09-19 08:00:05 +02:00
|
|
|
import scala.concurrent.duration._
|
2012-05-29 08:28:54 +02:00
|
|
|
import akka.actor.Actor
|
|
|
|
|
import akka.actor.ActorRef
|
2012-05-29 13:18:46 +02:00
|
|
|
import akka.actor.Address
|
2013-09-19 08:00:05 +02:00
|
|
|
import akka.actor.PoisonPill
|
|
|
|
|
import akka.actor.Props
|
2016-09-19 13:22:54 +02:00
|
|
|
import akka.remote.RemotingMultiNodeSpec
|
2018-12-05 16:30:21 +08:00
|
|
|
import akka.remote.testkit.MultiNodeConfig
|
2012-05-29 08:28:54 +02:00
|
|
|
import akka.routing.Broadcast
|
2013-09-19 08:00:05 +02:00
|
|
|
import akka.routing.RandomPool
|
2012-05-29 08:28:54 +02:00
|
|
|
import akka.routing.RoutedActorRef
|
|
|
|
|
import akka.testkit._
|
2016-06-02 20:44:27 +02:00
|
|
|
import com.typesafe.config.ConfigFactory
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2016-06-02 20:44:27 +02:00
|
|
|
class RemoteRandomConfig(artery: Boolean) extends MultiNodeConfig {
|
2012-05-29 08:28:54 +02:00
|
|
|
|
|
|
|
|
val first = role("first")
|
|
|
|
|
val second = role("second")
|
|
|
|
|
val third = role("third")
|
|
|
|
|
val fourth = role("fourth")
|
|
|
|
|
|
2016-06-02 20:44:27 +02:00
|
|
|
commonConfig(debugConfig(on = false).withFallback(
|
|
|
|
|
ConfigFactory.parseString(s"""
|
|
|
|
|
akka.remote.artery.enabled = $artery
|
2016-11-23 12:02:36 +01:00
|
|
|
""")).withFallback(RemotingMultiNodeSpec.commonConfig))
|
2012-05-29 08:28:54 +02:00
|
|
|
|
|
|
|
|
deployOnAll("""
|
2013-09-19 08:00:05 +02:00
|
|
|
/service-hello {
|
|
|
|
|
router = "random-pool"
|
|
|
|
|
nr-of-instances = 3
|
|
|
|
|
target.nodes = ["@first@", "@second@", "@third@"]
|
|
|
|
|
}
|
2012-05-29 08:28:54 +02:00
|
|
|
""")
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-02 20:44:27 +02:00
|
|
|
class RemoteRandomMultiJvmNode1 extends RemoteRandomSpec(new RemoteRandomConfig(artery = false))
|
|
|
|
|
class RemoteRandomMultiJvmNode2 extends RemoteRandomSpec(new RemoteRandomConfig(artery = false))
|
|
|
|
|
class RemoteRandomMultiJvmNode3 extends RemoteRandomSpec(new RemoteRandomConfig(artery = false))
|
|
|
|
|
class RemoteRandomMultiJvmNode4 extends RemoteRandomSpec(new RemoteRandomConfig(artery = false))
|
|
|
|
|
|
|
|
|
|
class ArteryRemoteRandomMultiJvmNode1 extends RemoteRandomSpec(new RemoteRandomConfig(artery = true))
|
|
|
|
|
class ArteryRemoteRandomMultiJvmNode2 extends RemoteRandomSpec(new RemoteRandomConfig(artery = true))
|
|
|
|
|
class ArteryRemoteRandomMultiJvmNode3 extends RemoteRandomSpec(new RemoteRandomConfig(artery = true))
|
|
|
|
|
class ArteryRemoteRandomMultiJvmNode4 extends RemoteRandomSpec(new RemoteRandomConfig(artery = true))
|
|
|
|
|
|
|
|
|
|
object RemoteRandomSpec {
|
|
|
|
|
class SomeActor extends Actor {
|
|
|
|
|
def receive = {
|
|
|
|
|
case "hit" ⇒ sender() ! self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2016-09-19 13:22:54 +02:00
|
|
|
class RemoteRandomSpec(multiNodeConfig: RemoteRandomConfig) extends RemotingMultiNodeSpec(multiNodeConfig)
|
2016-09-16 15:12:40 +02:00
|
|
|
with DefaultTimeout {
|
2016-06-02 20:44:27 +02:00
|
|
|
import multiNodeConfig._
|
|
|
|
|
import RemoteRandomSpec._
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2013-09-19 08:00:05 +02:00
|
|
|
def initialParticipants = roles.size
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2013-09-19 08:00:05 +02:00
|
|
|
"A remote random pool" must {
|
2012-05-29 14:30:15 +02:00
|
|
|
"be locally instantiated on a remote node and be able to communicate through its RemoteActorRef" taggedAs LongRunningTest in {
|
2012-05-29 08:28:54 +02:00
|
|
|
|
|
|
|
|
runOn(first, second, third) {
|
2012-06-15 14:39:47 +02:00
|
|
|
enterBarrier("start", "broadcast-end", "end", "done")
|
2012-05-29 08:28:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runOn(fourth) {
|
2012-06-15 14:39:47 +02:00
|
|
|
enterBarrier("start")
|
2013-09-19 08:00:05 +02:00
|
|
|
val actor = system.actorOf(RandomPool(nrOfInstances = 0).props(Props[SomeActor]), "service-hello")
|
2015-01-16 11:09:59 +01:00
|
|
|
actor.isInstanceOf[RoutedActorRef] should ===(true)
|
2012-05-29 08:28:54 +02:00
|
|
|
|
|
|
|
|
val connectionCount = 3
|
2013-02-22 12:12:58 +01:00
|
|
|
val iterationCount = 100
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2012-05-29 13:18:46 +02:00
|
|
|
for (i ← 0 until iterationCount; k ← 0 until connectionCount) {
|
|
|
|
|
actor ! "hit"
|
|
|
|
|
}
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2013-09-19 08:00:05 +02:00
|
|
|
val replies: Map[Address, Int] = (receiveWhile(5.seconds, messages = connectionCount * iterationCount) {
|
2012-05-29 13:18:46 +02:00
|
|
|
case ref: ActorRef ⇒ ref.path.address
|
2016-06-02 14:06:57 +02:00
|
|
|
}).foldLeft(Map(node(first).address → 0, node(second).address → 0, node(third).address → 0)) {
|
|
|
|
|
case (replyMap, address) ⇒ replyMap + (address → (replyMap(address) + 1))
|
2012-05-29 08:28:54 +02:00
|
|
|
}
|
|
|
|
|
|
2012-06-15 14:39:47 +02:00
|
|
|
enterBarrier("broadcast-end")
|
2012-05-29 13:18:46 +02:00
|
|
|
actor ! Broadcast(PoisonPill)
|
2012-05-29 08:28:54 +02:00
|
|
|
|
2012-06-15 14:39:47 +02:00
|
|
|
enterBarrier("end")
|
2013-02-22 12:12:58 +01:00
|
|
|
// since it's random we can't be too strict in the assert
|
2013-12-17 14:25:56 +01:00
|
|
|
replies.values count (_ > 0) should be > (connectionCount - 2)
|
2015-01-16 11:09:59 +01:00
|
|
|
replies.get(node(fourth).address) should ===(None)
|
2012-05-29 08:28:54 +02:00
|
|
|
|
|
|
|
|
// shut down the actor before we let the other node(s) shut down so we don't try to send
|
|
|
|
|
// "Terminate" to a shut down node
|
|
|
|
|
system.stop(actor)
|
2012-06-15 14:39:47 +02:00
|
|
|
enterBarrier("done")
|
2012-05-29 08:28:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-06-02 20:44:27 +02:00
|
|
|
}
|