DistributedPubSubMediator通过代理Actor订阅无法正常工作

时间:2013-10-21 08:03:52

标签: scala akka

我的同事和我一直对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是否是一个好习惯?

目前我们有:

  1. 订阅应用程序发现发布应用程序(以非Akka方式)并获取群集地址。
  2. 远程用户使用此地址和已知代理参与者的路径发送身份请求。
  3. 远程用户获取ActorIdentity响应,然后通过此(远程)代理获取/取消订阅。
  4. 在发布者App上,订阅/取消订阅消息将转发到DistributedPubSubMediator,并用于发布后续业务消息。
  5. 根据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)
      }
    }
    

1 个答案:

答案 0 :(得分:1)

两件事:

  • 您是否使用forward并不重要,因为您的测试程序中没有有用的发件人(您没有混合使用ImplicitSender);但这不是问题
  • 您没有转发Publish消息,这就是它不发布消息的原因