私は AKKA2 を初めて使用します。以下は私の質問です。
サーバー アクターといくつかのクライアント アクターがあります。サーバーは、クライアント アクターのすべての参照を格納します。
どのクライアントが切断されているかをサーバーがどのように検出できるのだろうか(シャットダウン、クラッシュ...)
また、サーバーが停止していることをクライアントに伝える方法があれば。
私は AKKA2 を初めて使用します。以下は私の質問です。
サーバー アクターといくつかのクライアント アクターがあります。サーバーは、クライアント アクターのすべての参照を格納します。
どのクライアントが切断されているかをサーバーがどのように検出できるのだろうか(シャットダウン、クラッシュ...)
また、サーバーが停止していることをクライアントに伝える方法があれば。
アクターのライフサイクルを操作するには、2 つの方法があります。まず、アクターの親は、アクターの障害を処理する監視ポリシーを定義し、障害後に再起動、停止、再開、またはエスカレートするオプションを備えています。さらに、スーパーバイザー以外のアクターは、アクターを「監視」して、アクターが死亡したときに生成される終了メッセージを検出できます。ドキュメントのこのセクションでは、トピックについて説明しています: http://doc.akka.io/docs/akka/2.0.1/general/supervision.html
仕様からの時計の使用例を次に示します。アクターを開始し、Termination のウォッチャーをセットアップします。アクターが PoisonPill メッセージを受け取ると、ウォッチャーによってイベントが検出されます。
"be able to watch the proxy actor fail" in {
val myProxy = system.actorOf(Props(new VcdRouterActor(vcdPrivateApiUrl, vcdUser, vcdPass, true, sessionTimeout)), "vcd-router-" + newUuid)
watch(myProxy)
myProxy ! PoisonPill
expectMsg(Terminated(`myProxy`))
}
認証例外が原因で失敗した場合は子アクターを停止するカスタム スーパーバイザー戦略の例を次に示します。これはおそらく修正できないためです。または、失敗が別の理由によるものである場合は、失敗を上位のスーパーバイザーにエスカレートします。
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 5, withinTimeRange = 1 minutes) {
// presumably we had a connection, and lost it. Let's restart the child and see if we can re-establish one.
case e: AuthenticationException ⇒
log.error(e.message + " Stopping proxy router for this host")
Stop
// don't know what it was, escalate it.
case e: Exception ⇒
log.warning("Unknown exception from vCD proxy. Escalating a {}", e.getClass.getName)
Escalate
}
アクター内で、例外をスローするか、PoisonPill メッセージを処理することによって、失敗を生成できます。
失敗を生成したくない場合に役立つ可能性がある別のパターンは、送信者に失敗で応答することです。その後、発信者とより個人的なメッセージ交換を行うことができます。たとえば、呼び出し元は ask パターンを使用し、応答を処理するために onComplete ブロックを使用できます。発信者側:
vcdRouter ? DisableOrg(id) mapTo manifest[VcdHttpResponse] onComplete {
case Left(failure) => log.info("receive a failure message")
case Right(success) ⇒ log.info("org disabled)
}
呼び出し側:
val org0 = new UUID("00000000-0000-0000-0000-000000000000")
def receive = {
case DisableOrg(id: UUID) if id == org0 => sender ! Failure(new IllegalArgumentException("can't disable org 0")
case DisableOrg(id: UUID) => sender ! disableOrg(id)
}
サーバーがリモート クライアントの状態の変化に反応するようにするには、次のようなものを使用できます (例は Akka 2.1.4 の場合です)。
Javaで
@Override
public void preStart() {
context().system().eventStream().subscribe(getSelf(), RemoteLifeCycleEvent.class);
}
またはScalaで
override def preStart = {
context.system.eventStream.subscribe(listener, classOf[RemoteLifeCycleEvent])
}
クライアントが切断されたときにのみ関心がある場合は、RemoteClientDisconnected にのみ登録できます。
詳細はこちら(Java)およびこちら(scala)