2012-03-05 6 views
21

私はAkkaとそのJava API UntypedActorを使用してActorシステムを実装しました。その中で、1人のアクター(タイプA)は、getContext().actorOf(...);を使用して、オンデマンドで他のアクター(タイプB)を動的に開始します。これらのBアクターは、Aが本当に気にしない計算を行います。しかし、私は思っています:彼らが終了したらタイプBのそれらの俳優をきれいにする必要がありますか?もしそうなら、どうですか?Akka:ダイナミックに作成されたアクターのクリーンアップが完了したら必要ですか?

  • Bアクターが完了したときにgetContext().stop(getSelf())と呼ぶことによって、
  • Bアクターが完了したらgetSelf().tell(Actors.poisonPill());と呼ぶことによって、 [これは私が今使っているものです]。
  • 何もしないことで?
  • By ...?

ドキュメントはこれではっきりしないか、見落としてしまいました。私はScalaに関するいくつかの基本的な知識を持っていますが、Akkaソースはエントリーレベルのものではありません...

答えて

23

あなたが記述しているのは、一連のイベントを処理して完了した「要求」(Aのコンテキストで定義)ごとに作成された単目的のアクターです。それは絶対にうまくいきます。そして、あなたはそれらを止めることが正しければなりません。そうしないと、時間の経過とともに蓄積され、あなたはメモリリークに遭遇します。これを行う最善の方法は、あなたが言及した可能性のうちの最初のもの(最も直接的)ですが、2番目の方法も大丈夫です。

バックグラウンドのビット:アクターは、識別可能にするために親の中に登録されています(例えば、リモーティングで必要ですが、他の場所でも必要です)。この登録はガベージコレクションを維持します。 OTOHでは、各親は作成した子にアクセスする権利があります。したがって、自動終了(つまりAkkaによる)は意味をなしません。代わりにユーザーコードでの明示的な停止が必要です。

+0

http:// stackoverflow。com/questions/23066264/can-wrapping-akka-actor-in-class-actor-起因メモリリーク< - 関連の質問 –

-3

アクターはデフォルトでは多くのメモリを消費しません。アプリケーションが後でアクターbを使用する予定の場合、それらを有効に保つことができます。もしそうでなければ、あなたはpoisonpillでそれらをシャットダウンすることができます。あなたの俳優が資源を持っていない限り、俳優を残しても大丈夫です。

+4

しかし、Rolandが指摘しているように、アクターはガベージコレクションされないため、時間の経過とともに蓄積されます。>メモリリーク。 –

0

リクエストごとに新しいアクタを作成するのではなく、同じディスパッチャを共有するアクタの定義済みセットを作成することも、アクタのプールにリクエストを配信するルータを使用することもできます。

Balancing Pool Routerは、たとえば、あなたが特定の種類の株式の俳優の固定セットに同じメールボックスを持つことができます:

akka.actor.deployment { 
    /parent/router9 { 
    router = balancing-pool 
    nr-of-instances = 5 
    } 
} 

さらに詳細についてdispatchers上とroutingのマニュアルを参照してください。

0

私はAKKAドキュメントのサンプルクラスタアプリケーションの1つをプロファイリング(visualvm)していました。ガベージコレクションでは、すべてのGCでリクエストアクターをクリーンアップしています。使用後に明示的に俳優を殺すという推奨を完全に理解できません。私のアクターシステムとアクターはSPRING IOCコンテナーによって管理され、私はアクターを作成するために春の拡張機能の直接アクタープロデューサーを使用します。 "アグリゲーター"アクターはすべてのGCでガベージコレクションされています。私は、ビジュアルVMのインスタンス数を監視しました。

@Component 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
public class StatsService extends AbstractActor { 

    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); 

    @Autowired 
    private ActorSystem actorSystem; 

    private ActorRef workerRouter; 

    @Override 
    public void preStart() throws Exception { 
     System.out.println("Creating Router" + this.getClass().getCanonicalName()); 
     workerRouter = getContext().actorOf(SPRING_PRO.get(actorSystem) 
      .props("statsWorker").withRouter(new FromConfig()), "workerRouter"); 
     super.preStart(); 
    } 

    @Override 
    public Receive createReceive() { 
     return receiveBuilder() 
      .match(StatsJob.class, job -> !job.getText().isEmpty(), job -> { 
       final String[] words = job.getText().split(" "); 
       final ActorRef replyTo = sender(); 
       final ActorRef aggregator = getContext().actorOf(SPRING_PRO.get(actorSystem) 
        .props("statsAggregator", words.length, replyTo)); 

       for (final String word : words) { 
        workerRouter.tell(new ConsistentHashableEnvelope(word, word), 
         aggregator); 
       } 
      }) 
      .build(); 
    } 
} 
関連する問題