Akkaシリーズ(二):AkkaにおけるActorシステム


ActorモデルはAkkaの最も核心的な概念であるため,AkkaにおけるActorの組織構造も重要であり,本稿では主にAkkaにおけるActorシステムを紹介する.
Actorシステム
Actorはカプセル化された状態と行為の対象として、常にシステムを統一して組織し、管理する必要があります.AkkaではActorSystemですが、これは非常に理解しやすいです.例えば、会社では、従業員一人一人がActorと見なすことができます.彼らには自分のポジションと職責がありますが、従業員を集めて、管理と割り当ての任務を統一する必要があります.ここのActorSystemがActorを管理しているように、対応するシステムが必要です.
ActorSystemの主な機能
ActorSystemには主に以下の3つの機能があります.
  • 管理スケジューリングサービス
  • 関連パラメータ
  • の構成
  • ログ機能
  • 1.スケジューリングサービスの管理
    ActorSystemの真髄は、1つのタスクが完全に処理されるほど小さくなるまでタスクを分割し、Actorに処理を依頼することにあるので、ActorSystemの最も核心的な機能はシステム全体の運行を管理し、スケジューリングすることであり、会社の管理者のように、会社全体の発展計画を制定する必要があります.また、対応するスタッフに仕事を割り当てて完成させ、会社全体の正確な運営を保障する必要があります.実は、ここでもソフトウェア設計の分而治之を体現しています.Actorの核心思想もそうです.
    ActorSystemモデルの例:
    上の図は簡単な開発コラボレーションの過程で、この例はAkkaのActorの組織構造を明確に表現できると思います.もちろんそれだけではありません.主に以下の特徴があります.
  • AkkaにおけるActorの組織は木構造
  • である.
  • 各Actorには親があり、子がある可能性もあります.もちろん
  • はありません.
  • 親Actorは、その子Actorにリソース、タスクを割り当て、そのライフ・ステータス(監視と監視)
  • を管理します.
    Actorシステムには何千ものActorがあり、ツリー機構を使用してActorを組織管理するのに適しています.
    しかもAkkaは生まれながらにして分散型で、リモートのActorにメッセージを送信することができますが、このActorの具体的な位置がどこにあるかを知る必要があります.このとき、ツリー構造はActorのパスを特定するのに非常に有利であることがわかります(Linuxのファイルストレージなど)、Actorがツリー構造で組織されているのは完璧だと思います.
    2.構成に基づいて環境を作成する
    完全なActorSystemには、使用するログ管理、異なる環境で印刷されるログレベル、ブロッカー、メールボックスなど、関連する構成情報が必要です.AkkaはTypesafe構成ライブラリを使用しています.これは非常に強力な構成ライブラリです.その後、私も後続の文章を書くつもりです.皆さん、楽しみにしてください.
    次に、アクセサシステムがプロファイルの内容に基づいて対応するアクセサシステム環境を生成する簡単な例を示します.
    1.まず、デフォルトの構成に従ってシステムのログレベルを印刷し、Akka環境を構築します.私の前の文章を見てください.Akkaシリーズ(一):Akka概要とActorモデル
    val actorSystem = ActorSystem("robot-system")
    println(s"the ActorSystem logLevel is ${actorSystem.settings.LogLevel}")
      

    実行結果:
    the ActorSystem logLevel is INFO

    ActorSystemのデフォルトのログ出力レベルはINFOであることがわかります.
    2.今アプリケーションにいます.confではログの出力レベルを設定します.
    akka {
    
    # Log level used by the configured loggers (see "loggers") as soon
    # as they have been started; before that, see "stdout-loglevel"
    # Options: OFF, ERROR, WARNING, INFO, DEBUG
    loglevel = "DEBUG"
    }

    実行結果:
    [DEBUG] [03/26/2017 12:07:12.434] [main] [EventStream(akka://robot-system)] logger log1-Logging$DefaultLogger started
    [DEBUG] [03/26/2017 12:07:12.436] [main] [EventStream(akka://robot-system)] Default Loggers started
    the ActorSystem logLevel is DEBUG

    ActorSystemのログ出力レベルはDEBUGになっていることがわかります.ここでは主に、アクセサシステムがプロファイルの内容に応じて適切な環境をロードし、アクセサシステム全体に適用できることを示します.これは、アクセサシステム環境の構成にとって非常に便利です. 
    3.ログ機能
    多くの人が疑問に思うかもしれませんが、ログはプログラムの実行状態を記録し、エラーを排除するだけではありませんか.どのようにAkkaの中で重要になりますか.Akkaは高いフォールトトレランスメカニズムを持っています.これは、Actorエラーの後、Akkaの持続化など、適切なリカバリ戦略をタイムリーに行うには、完全なログ記録が必要です.具体的な役割は、後で該当する章を書き続けるときに言及するかもしれません.
    Actorリファレンス、パス、アドレス
    上記の知識があれば、ここでActorリファレンスを理解すると、パスとアドレスが簡単になります.
    Actorリファレンスはいつですか?
    ActorリファレンスはActorRefのサブクラスであり、各Actorには一意のActorRefがあり、ActorリファレンスはActorのエージェントと見なすことができ、Actorと付き合うにはActorリファレンスが必要であり、Actorリファレンスは対応するActorにメッセージを送信したり、メッセージを受信したりすることができ、Actorにメッセージを送信することは、実はActorに対応するリファレンスにメッセージを送信することであり、さらに、特定のActorのポストにメッセージを送信するので、ActorRefはActorシステム全体で非常に重要な役割を果たします.
    Actorリファレンスの入手方法
  • 直接作成Actor
  • 既存のActor
  • を検索
    1.ActorRefを取得する
    私の前の文章を見た学生はこのような方法でActorの引用を得たのは比較的に理解しているはずです.ここでは、ActorRefを得るいくつかの方法を具体的に説明します.
    今、ボスが市場のビジネスチャンスを嗅いで、新しいプロジェクトを開く準備をしていると仮定します.彼はマネージャーに要求を伝え、マネージャーは相応の需要に応じて、適切な従業員を手配して仕事をします.
    この例は簡単ですが、このシーンをシミュレートします.
    1.まず、いくつかのメッセージを作成します.
    trait Message {
      val content: String
    }
    case class Business(content: String) extends Message {}
    case class Meeting(content: String) extends Message {}
    case class Confirm(content: String, actorPath: ActorPath) extends Message {}
    case class DoAction(content: String) extends Message {}
    case class Done(content: String) extends Message {}
    

    2.ActorSystemの化身である会社を作ります.
    val actorSystem = ActorSystem("company-system") //          
    //  Actor  ActorRef     ,  ActorSystem.actorOf
    val bossActor = actorSystem.actorOf(Props[BossActor], "boss") //     Boss
    bossActor ! Business("Fitness industry has great prospects") //                   
      

    3.ここでは、上のボスなど、いくつかのロールを作成します.ここにはマネージャー、Workerもあります.見てみましょう.
    class BossActor extends Actor {
      val log = Logging(context.system, this)
      implicit val askTimeout = Timeout(5 seconds)
      import context.dispatcher
      var taskCount = 0
      def receive: Receive = {
        case b: Business =>
          log.info("I must to do some thing,go,go,go!")
          println(self.path.address)
          //  Actor  ActorRef      ,  ActorContext.actorOf
          val managerActors = (1 to 3).map(i =>
            context.actorOf(Props[ManagerActor], s"manager${i}")) //      3   
          //           
          managerActors foreach {
            _ ? Meeting("Meeting to discuss big plans") map {
              case c: Confirm =>
                //           Actor   ?
                //                         (     )
                log.info(c.actorPath.parent.toString)
                //  Actor         Actor  ActorRef
                //  c.actorPath     ,               ActorRef
                val manager = context.actorSelection(c.actorPath)
                manager ! DoAction("Do thing")
            }
          }
        case d: Done => {
          taskCount += 1
          if (taskCount == 3) {
            log.info("the project is done, we will earn much money")
            context.system.terminate()
          }
        }
      }
    }
    class ManagerActor extends Actor {
      val log = Logging(context.system, this)
      def receive: Receive = {
        case m: Meeting =>
          sender() ! Confirm("I have receive command", self.path)
        case d: DoAction =>
          val workerActor = context.actorOf(Props[WorkerActor], "worker")
          workerActor forward d
      }
    }
    
    class WorkerActor extends Actor {
      val log = Logging(context.system, this)
      def receive: Receive = {
        case d: DoAction =>
          log.info("I have receive task")
          sender() ! Done("I hava done work")
      }
    }

    このコードを見るだけでは理解しにくいかもしれませんが、ここではこのプログラムを理解するためのフローチャートを描きます.
    プログラムフローチャート:
    上のフローチャートを見てプログラムに対してある程度理解したはずで、多すぎる解釈は私のここで説明しないで、注釈を見て、あるいはソースコードをダウンロードして自分で走ってみることができます.ソースリンク
    ここには主に2つの知識点があります.
  • Actorを作成してActorRefを得る2つの方法
  • .
  • Actorパスに従ってActorRef
  • を取得する.
    前の知識点ははっきりしているはずですが、具体的には2つ目です.
    2.Actorパスとアドレス
    類Unixシステムに詳しい学生は経路という概念に詳しいはずだ.ActorSystemにおける経路も同様であり、各ActorSystemにはルートガードが1人おり、/で表され、ルートガードの下にはuserという名前のActorがあり、それはすべてのsystemである.ActorOf()で作成された親Actorなので、私たちのプログラムのbossActorのパスは次のとおりです./user/boss
    アドレスはその名の通りActorの位置にあり、なぜアドレスという概念があるのか、これがAkkaの強力な理念であり、Akkaの中のすべてのものは分散環境で動作するように設計されています.任意の場所のActorにメッセージを送信することができます(どこにあるかを知っておく必要があります)、アドレスの役割が現れます.まず、アドレスに基づいてActorがどこにあるかを見つけ、パスに基づいて具体的なActorを見つけることができます.例えば、プログラムのbossActorのように、その完全な位置はakka://company-system/user/boss
    住所はakka://company-system
    ここで、akkaは純粋なローカルを表し、Akkaにおけるデフォルトのリモートアクセサの位置は一般的にakkaを用いる.tcpかakka.udpの冒頭では、もちろんサードパーティ製のプラグインを使用することもできますが、Akkaのリモートコールは私も専門的に文章を書くことができます.
    総じて言えば、この文章は主にActorSystemのインフラストラクチャ、関連配置、およびActorの引用、経路と住所などの比較的基礎的な知識点を説明して、これは実は全体のActorシステムがどのように運行しているかを理解するのにとても役に立ち、ブロガーも長い間書いて、書くのが分かりやすいことを努力して、みんなの支持を得ることができることを望んでいます.次の記事では、Actorの監督管理と監視、ライフサイクルについて説明します.興味のある同級生も私の個人ブログに注目することができます.