AKKAのactorの少しの個人的な理解に対して

5519 ワード

AKKAのactorの少しの個人的な理解に対して
  • Actorとは何ですか
  • Actorとスレッドの違い
  • Actorがどのように実行するか
  • Actor
  • をブロックしないでください.
  • Actorを慎むask法
  • thoughtputの一点思考
  • Actorとは
    actorがcpuのタイムスライスだという話を聞いたことがあるが、この説は非常に適切だ.Actor間でメッセージを介して通信するのは,すべて非同期である.Actorは現実の人々のように、それぞれの役割を果たし、互いにメッセージを通じて交流し、あるactorが別のactorから送信されたメッセージを受け取った後、メッセージの内容に従って指定されたタスクを実行し、その後、新しいタスクを伝えたり、実行結果をメッセージ送信者に返したりすると言える.Actorというモデルは従来のjava同時発生による様々な問題をよく解決している.
    Actorとスレッドの違い
    Actorは従来のマルチスレッドロックの問題を回避し、Actorには共有変数がなく、すべてが無状態である.actorで新しいスレッドを呼び出して非同期操作を行うことができるが、これはActor自体の理念に合致せず、Actorの全体的な設計を破壊する.Actorは単一スレッドで実行され、1つのActorが同時に1つのメッセージしか処理できないことを覚えておいてください.Actorの数を増やすことで、システムの並列処理の能力を高めることができます.
    Actorの実行方法
    AKAではdispatcherを使用してactorを実行し、actorが起動するとdispatcherに自身をバインドし、システム構成で独自のdispathcerを定義できます.Dispatcher自体は実際にはスレッドプールであり、デフォルトのdispatcherはfork-join-executorであり、読者は次の表を参照して理解できないdispatcherを理解することができる.
    Dispathcer
    適用シーン
    デフォルトDispatcher
    ほとんどのシーンに適した既定の実装
    PinnedDispatcher
    優先度の高いactorに適し、actorに独立したスレッドを使用
    BalancingDispatcher
    このdispatcherを使用するactorは、同じタイプのactorにのみ適したメールボックスを共有し、2.3バージョン以降はBalancingPoolに置き換えられます.
    簡単なdispatcher構成
    default-dispatcher {
       executor = "fork-join-executor"//  executor
       fork-join-executor {
         parallelism-min = 8
         parallelism-factor = 2.0
         parallelism-max = 8//       
       }
     }

    Actorをブロックしない
    Actorの重要なガイドラインは、Actor自体が単一スレッドでメッセージを処理しているため、ブロックされるとメッセージが蓄積し、dispatcherリソースが大量に占有されるなどの問題が発生するため、筆者の現在のプロジェクトではfutureを使用してIOブロッククラスの操作を処理するのが一般的である.もう1つの考え方は、ブロックが存在する操作のために複数の独立したactorを作成し、これらのactorを独立したdispatcherにバインドし、ブロックactorを従来のactorから隔離し、他のactorの実行に影響を与えないようにすることです.
    独立したdispatcherを構成することによってActorを分離する
    //              dispatcher
     crawler-dispatcher{
      type=Dispatcher
      executor = "thread-pool-executor"
      thread-pool-executor{
        core-pool-size-min = 4
        core-pool-size-max = 64
      }
      throughput=5
    }
    
    //    withDispatcher    actor   dispatcher
     val actor = context.actorOf(Props[MyActor].withDispatcher("crawler-dispatcher"))

    Actorのaskメソッドを慎む
    方法
    区別する
    じっこうモード
    tell
    Fire and forget、送信後すぐに戻ります
    ダイレクト送信
    ask
    送信後しばらく待機してfutureに戻ります
    中間エージェントを作成して再送信
    上の表ではtellとaskの違いを示していますが、akkaのソースコードを読むと、askを使用するとactorが一時的なエージェントActorを生成してメッセージを送信し、askを乱用するとシステムの性能に大きな影響を与えることがわかりますので、注意が必要です.
    //akka   ask     actorRef
    val a = PromiseActorRef(ref.provider, timeout, targetName = actorRef, message.getClass.getName, sender)
            actorRef.tell(message, a)
            a.result.future

    thoughtputの少しの思考
    上記ではdispatcherの違いと使用方法について説明したが、thoughtputというパラメータもあり、akkaの公式ドキュメントではこのように記述されている.#Throughput defines the maximum number of messages to be#processed per actor before the thread jumps to the next actor.#Set to 1 for as fair as possible. このパラメータを読むと、actorがスレッドを取得した後に処理するメッセージの数を設定することができ、1に設定すると公平なモードになり、設定が大きい場合、現在のactorは指定された数のメッセージが消費されるまでスレッドを占有することができます.私たちのcpuコンテキストの切り替えが多すぎる場合は、この値を大きく設定することを考慮することができます.メッセージの数自体が少ない場合、設定が大きすぎると、actorがスレッドの空を占めているなどのメッセージが他のactorの実行に影響します.具体的な設定は、自分で模索する必要があります.
    default-dispatcher {
       executor = "fork-join-executor"
       fork-join-executor {
         parallelism-min = 8
         parallelism-factor = 2.0
         parallelism-max = 8
       }
       thoughtput = 5//    actor            ,        cpu       
     }