我的同事和我一直对DistributedPubSubMediator用于直接订阅/取消订阅或通过代理Actor的不同行为感到困惑。我们整理了一个测试,以显示下面的不同结果。
根据我们的理解,ActorRef.forward应该传入原始发件人,因此消息是直接发送给Mediator还是通过代理Actor应该无关紧要。 IE浏览器。 http://www.scala-lang.org/api/current/index.html#scala.actors.ActorRef。
要解决此问题,我们必须扩展DIstributedPubSubMediator类并包含已提供的逻辑DistributedPubSubMediator对象。理想情况下,我们更喜欢直接使用对象并还原我们的代码。
这似乎是一个错误。有谁知道这种不寻常行为的根本原因?请帮忙......
[2013年10月22日]根据Roland的回答更新测试(谢谢),并在SubscriberAck和UnsubscribeAck上添加了expectMsgType。我们现在收到SubscribeAck,但奇怪的是不是UnSubscribeAck。这不是一个重大问题,但我们想知道原因。
另一个问题,如果我们可以完全问,是通过在同一个ActorSystem中运行的代理Actor将远程actor订阅到DistributedPubSubMediator是否是一个好习惯?
目前我们有:
根据Akka Reactor pubsub聊天客户端示例(即仅使用DistributedPubSubMediator发布),我们没有加入群集,因为我们需要在发布者端处理故障转移。
[2013年11月5日]在发送消息上添加了测试。它似乎不起作用,我们还没有想出来。
package star.common.pubsub
import org.scalatest.{BeforeAndAfterAll, FunSuite}
import org.junit.runner.RunWith
import akka.contrib.pattern.DistributedPubSubExtension
import akka.contrib.pattern.DistributedPubSubMediator._
import akka.testkit.TestKit
import akka.actor.{Actor, ActorSystem, ActorRef, Props}
import scala.concurrent.duration._
import com.typesafe.config.ConfigFactory
object MediatorTest {
val config = ConfigFactory.parseString(s"""
akka.actor.provider="akka.cluster.ClusterActorRefProvider"
akka.remote.netty.tcp.port=0
akka.extensions = ["akka.contrib.pattern.DistributedPubSubExtension"]
""")
}
@RunWith(classOf[org.scalatest.junit.JUnitRunner])
class MediatorTest extends TestKit(ActorSystem("test", MediatorTest.config)) with FunSuite {
val mediator = DistributedPubSubExtension(system).mediator
val topic = "example"
val message = "Published Message"
// val joinAddress = Cluster(system).selfAddress
// Cluster(system).join(joinAddress)
test("Direct subscribe to mediator") {
mediator.!(Subscribe(topic, testActor))(testActor)
expectMsgType[SubscribeAck](5 seconds)
mediator.!(Publish(topic, message))(testActor)
expectMsg(2 seconds, message)
mediator.!(Unsubscribe(topic, testActor))(testActor)
expectMsgType[UnsubscribeAck](5 seconds)
mediator ! Publish(topic, message)
expectNoMsg(2 seconds)
}
test("Subscribe to mediator via proxy") {
class Proxy extends Actor {
override def receive = {
case subscribe: Subscribe =>
mediator forward subscribe
case unsubscribe: Unsubscribe =>
mediator forward unsubscribe
case publish: Publish =>
mediator.!(publish)
}
}
val proxy = system.actorOf(Props(new Proxy), "proxy")
proxy.!(Subscribe(topic,testActor))(testActor)
expectMsgType[SubscribeAck](2 seconds)
proxy ! Publish(topic, message)
expectMsg(5 seconds, message)
proxy.!(Unsubscribe(topic,testActor))(testActor)
expectMsgType[UnsubscribeAck](5 seconds)
proxy ! Publish(topic, message)
expectNoMsg(5 seconds)
}
test("Send message to address") {
val testActorAddress = testActor.path.toString
// val system2 = ActorSystem("test", MediatorTest.config)
// Cluster(system2).join(joinAddress)
mediator.!(Subscribe(topic, testActor))(testActor)
expectMsgType[SubscribeAck](5 seconds)
println(testActorAddress) // akka://test/system/testActor1
mediator.!(Publish(topic, message))(testActor)
expectMsg(2 seconds, message)
mediator ! Send(testActorAddress, message, false)
expectMsg(5 seconds, message)
}
}
答案 0 :(得分:1)
两件事:
forward
并不重要,因为您的测试程序中没有有用的发件人(您没有混合使用ImplicitSender
);但这不是问题Publish
消息,这就是它不发布消息的原因