7

他のアクターのサービス層アクターによって一般的に使用されるものがあるとしましょう。たとえば、ドメイン オブジェクトを格納および取得するレジストリ サービスは次のとおりです。

case class DomainObject(id: UUID)

class Registry extends akka.actor.Actor {
  def receive: Receive = {
    case o: DomainObject => store(o) // save or update object

    case id: UUID => sender ! retrieve(id) // retrieve object and send it back
  }
}

そのようなレジストリのインスタンスを、それを使用する可能性のあるすべてのアクターに明示的に渡したくありません。その代わりに、どういうわけかそれを「見つける」ことができるようにしてほしい.

このために、私は2つの解決策を考えることができます:

  1. Identifyメッセージ: 各レジストリ ユーザー アクターは、何らかの構成からレジストリ アクター名を認識しており、識別メッセージを送信できます。AgentIdentityメッセージが返されたら、次の手順に進みます。

    val registryName = ... // some name
    val registryId = ... // some id
    var registry = _
    
    def preStart() {
      context.actorSelection(registryName) ! Identify(registryId)
    }
    
    def receive: Receive = {
      case ActorIdentity(`registryId`, ref) => registry = ref
    }
    

    ユーザー アクターの初期化の直後に、システムなどにレジストリがあるかどうかがわからず、操作できるかどうかがわからないフェーズがあるため、この方法は好きではありません。

  2. Akka 拡張機能: 次のような拡張機能を作成できます。

    を。初期化時に指定されたアクター システムにレジストリ アクターのインスタンスを作成します。

    b. エクステンションの何らかのメソッドを介して、このアクターを必要とするユーザーに返します。

    object RegistryKey extends ExtensionKey[RegistryExtension]
    
    class RegistryExtesion(system: ExtendedActorSystem) extends RegistryKey {
      val registry = system.actorOf(Props[Registry], "registry")
    }
    

問題は、どちらの方法が優れているか、そして Akka Extesions をこれに使用できるかどうかです。

4

2 に答える 2

3

レジストリ アクターが常に同じActorSystem.

または、 ( Remote LookupactorSelectionから適応)を使用:

class RegistryClient extends Actor {
  val path = "/path/to/registry/actor"
  context.setReceiveTimeout(3.seconds)

  def sendIdentifyRequest(): Unit =
    context.actorSelection(path) ! Identify(path)

  def receive = {
    case ActorIdentity(`path`, Some(ref)) ⇒
      context.setReceiveTimeout(Duration.Undefined)
      context.become(active(ref))
    case ActorIdentity(`path`, None) ⇒
      throw new RuntimeException("Registry not found")
    case ReceiveTimeout ⇒ sendIdentifyRequest() 
  }

  def active(registry: ActorRef): Actor.Receive = {
    // use the registry
  }
}

これは、リモート アクターまたはローカル アクターに対して機能します。

拡張ソリューションを見てみましょう。アクターは非同期的に作成されますactorOfしたがって、アクターが初期化に失敗した場合でも、 呼び出し時に拡張コンストラクターが失敗することはありません。

アクターが初期化に失敗したことを確実に知りたい場合、1 つの方法はask、アクターが応答する何かとその応答をアクターに伝えることAwaitです。アクターが応答しない場合、はAwaitをスローします。TimeoutException

class RegistryExtension(system: ExtendedActorSystem) extends Extension {
  val registry = system.actorOf(Props[Registry], "registry")
  implicit val timeout: Timeout = Timeout(500.millis)
  val f = registry ? "ping"    // Registry should case "ping" => "pong" 
  Await.result(f, 500.millis)  // Will throw a TimeoutException if registry fails 
                               // to respond
}

初めて呼び出すと、がTimeoutExceptionスローされます。RegistryExtension(system).registry

于 2013-06-09T14:59:44.050 に答える