3

私は Akka 2.1 のリモート アクターについて学んでおり、Typesafe が提供する反例を適応させようとしました。ティックを送信するために、コンソールからクイックアンドダーティ UI を実装しました。そして、現在のカウントを尋ねて(そして結果を表示して)終了します。

アイデアは、Counter アクターを実行するマスター ノードと、リモーティングを通じてそれにメッセージを送信するクライアント ノードを開始することです。ただし、構成とコードへの最小限の変更によってこれを実現したいと考えています。そのため、構成を変更することで、ローカル アクターを使用できます。

多くのインスタンスが実行されているにもかかわらず、すべての API 呼び出しが 1 つのアクターを経由する必要があるという同様の問題に関するこのブログ エントリを見つけました。

同様の構成を書きましたが、動作させることができません。私の現在のコードはリモーティングを使用していますが、新しいノードごとにマスターに新しいアクターを作成し、パスを明示的に指定しないと (そして構成のポイントに逆らいます)、既存のアクターに接続することはできません。ただし、この方法では JVM 間で状態を共有できないため、これは私が望むものではありません。

git リポジトリから利用可能な完全な実行可能なコード

これは私の設定ファイルです

akka {
    actor {
        provider = "akka.remote.RemoteActorRefProvider"
        deployment {
            /counter {
                remote = "akka://ticker@127.0.0.1:2552"
            }
        }
    }
    remote {
        transport = "akka.remote.netty.NettyRemoteTransport"
        log-sent-messages = on
        netty {
            hostname = "127.0.0.1"
        }
    }
}

そしてフルソース

import akka.actor._
import akka.pattern.ask
import scala.concurrent.duration._
import akka.util.Timeout
import scala.util._

case object Tick
case object Get

class Counter extends Actor {
  var count = 0

  val id = math.random.toString.substring(2)
  println(s"\nmy name is $id\ni'm at ${self.path}\n")
  def log(s: String) = println(s"$id: $s")

  def receive = {
    case Tick =>
      count += 1
      log(s"got a tick, now at $count")
    case Get  =>
      sender ! count
      log(s"asked for count, replied with $count")
  }
}

object AkkaProjectInScala extends App {
  val system = ActorSystem("ticker")
  implicit val ec = system.dispatcher

  val counter = system.actorOf(Props[Counter], "counter")

  def step {
    print("tick or quit? ")
    readLine() match {
      case "tick" => counter ! Tick
      case "quit" => return
      case _ =>
    }
    step
  }
  step

  implicit val timeout = Timeout(5.seconds)

  val f = counter ? Get
  f onComplete {
    case Failure(e) => throw e
    case Success(count) => println("Count is " + count)
  }

  system.shutdown()
}

sbt run別のウィンドウで andを使用sbt run -Dakka.remote.netty.port=0して実行しました。

4

2 に答える 2

1

ある種のパターンを使用できることがわかりました。Akka リモートは、リモート システムへの展開のみを許可します (設定だけでリモートを検索する方法が見つかりません..ここで間違っていますか?)。

したがって、ActorRef を返す「スカウト」をデプロイできます。ブランチ「scout-hack」の下の元のレポで利用可能な実行可能なコード。これはハックのように感じるからです。構成ベースのソリューションに感謝します。

俳優

case object Fetch

class Scout extends Actor{
  def receive = {
    case Fetch => sender ! AkkaProjectInScala._counter
  }
}

カウンター アクターの作成が遅延するようになりました

lazy val _counter = system.actorOf(Props[Counter], "counter")

したがって、(ポートによって決定される)マスターでのみ実行され、このようにフェッチできます

val counter: ActorRef = {
  val scout = system.actorOf(Props[Scout], "scout")
  val ref = Await.result(scout ? Fetch, timeout.duration) match {
    case r: ActorRef => r
  }
  scout ! PoisonPill
  ref
}

そして完全な設定

akka {
    actor {
        provider = "akka.remote.RemoteActorRefProvider"
        deployment {
            /scout {
                remote = "akka://ticker@127.0.0.1:2552"
            }
        }
    }
    remote {
        transport = "akka.remote.netty.NettyRemoteTransport"
        log-sent-messages = on
        netty {
            hostname = "127.0.0.1"
        }
    }
}

編集:私はまた、きれいな方法を見つけました:「counterPath」の構成を確認し、現在actorFor(path)が存在する場合はactorを作成します。いいですね。実行時にマスターを注入できます。コードは「スカウト」を使用する場合よりもはるかにクリーンですが、アクターをルックアップまたは作成するために天候を決定する必要があります。これは避けられないと思います。

于 2013-02-11T15:19:02.820 に答える
0

私はあなたのgitプロジェクトを試してみましたが、コンパイルエラーを除いて、実際に-Dakka.remote.netty.port=0は正常に動作し、パラメータとしてではなく、jvmへのパラメータを使用してsbtセッションを開始する必要がありますrun

また、両方のプロセスで Counter アクターを開始する必要がないことも理解する必要があります。この例では、クライアントから作成され、サーバー (ポート 2552) にデプロイされることを意図しています。サーバー上で起動する必要はありません。この例では、サーバー上にアクター システムを作成するだけで十分です。

于 2013-02-11T10:59:52.173 に答える