アクターとは何か?

アクターとは何か?

前のセクション アクターシステム では、アクターがどのように階層を形成し、アプリケーションを構築する際の最小単位であるかを説明しました。このセクションでは、そのようなアクターを単独で見て、それを実装する際に遭遇する概念について説明します。詳細は、 Actors (Scala)Untyped Actors (Java) を参照してください。

アクターは、 状態振る舞いメールボックス子アクタースーパーバイザー戦略 のコンテナです。これらのすべては アクター参照 の背後にカプセル化されています。注目すべき点の1つは、アクターが明示的なライフサイクルを持ち、参照されなくなったときに自動的に破棄されないことです。 作成した後、最終的に終了することを確実にすることはあなたの責任であり、また、 Actorを終了する時 にリソースを解放する方法を制御することができます。

アクター参照

以下に詳述するように、アクターモデルから恩恵を受けるためにアクターオブジェクトを外部から遮蔽する必要があります。 したがって、アクターは自由に、制限なしに渡すことができるオブジェクトであるアクター参照を使用して外部に現れます。 他の場所で参照を更新することなくアクターを再起動し、実際のアクターオブジェクトをリモートホストに配置し、まったく異なるアプリケーションでアクターにメッセージを送信します。 しかし、最も重要な側面は、アクターがこの情報自体を無差別に公表しない限り、アクターの内部を見て外部からその状態を保持することは不可能であるということです。

状態

Actorオブジェクトには通常、アクターが存在する可能性のある状態を反映する変数がいくつか含まれています。これは、明示的な状態マシン(例: FSM モジュールを使用)でもかまいません。また、 これらのデータは、アクターを高価なものにするものであり、他のアクターによる腐敗から保護されなければならない。 素晴らしいことに、Akkaのアクターは概念的にはそれぞれ軽量のスレッドを持ち、残りのシステムから完全に遮蔽されています。 つまり、ロックを使用してアクセスを同期させる代わりに、並行性を気にせずにアクターコードを書くことができます。

背後でAkkaは、通常は多くのアクターが1つのスレッドを共有し、1つのアクターの後続の呼び出しが異なるスレッドで処理される可能性がある実際のスレッドのセットでアクターのセットを実行します。 Akkaは、この実装の詳細がアクターの状態を処理するシングルスレッドに影響しないことを保証します。

内部状態はアクターの業務にとって不可欠であるため、矛盾した状態を持つことは致命的です。 したがって、アクターが失敗し、スーパーバイザーによって再起動されると、最初にアクターを作成したときのように、状態はゼロから作成されます。 これは、システムの自己治癒機能を有効にするためです。

オプションとして、アクターの状態は、受信したメッセージを永続化し、再起動後にリプレイすることで、再起動前の状態に自動的に回復することができます( 永続化 を参照)。

振る舞い

メッセージが処理されるたびに、アクターの現在の振る舞いと照合されます。 振る舞いとは、その時点でメッセージに反応するアクションを定義する関数を意味し、クライアントが許可されている場合は要求を転送し、それ以外の場合は否定します。 この振る舞いは時間の経過とともに変化する可能性があります。 異なるクライアントが時間の経過とともに権限を得るか、またはアクターが「out-of-service」モードに入り、後で戻ってくる可能性があるからです。 これらの変更は、振る舞いのロジックから読み込まれた状態変数をエンコードするか、実行時に関数自体をスワップアウトして、 becomeunbecome の操作を参照することによって実現されます。 しかし、アクターオブジェクトの構築中に定義される最初の振る舞いは、アクターの再起動がその振る舞いを初期アクションにリセットするという意味で特別です。

メールボックス

アクターの目的はメッセージの処理であり、これらのメッセージはアクターへ別のアクター(またはアクターシステムの外から)から送らます。 送信者と受信者を接続するのは、アクターのメールボックスです。各アクターは、すべての送信者がメッセージをエンキューするただ1つのメールボックスを持っています。 エンキューは送信操作の時間順に行われます。つまり、異なるアクターから送信されたメッセージは、スレッド間でアクターを分散させるという明らかなランダム性により、実行時に定義された順序を維持しない場合があります。 同じアクターから同じターゲットへ複数のメッセージを送信すると、同じ順序でエンキューされます。

さまざまなメールボックスの実装があり、デフォルトはFIFOです。つまり、アクターによって処理されるメッセージの順序は、エンキューされた順序と一致します。 これは通常、初期設定として適切ですが、アプリケーションはあるメッセージを別の優先順位付けにする必要があります。 この場合、優先度の高いメールボックスは、必ずしも最後ではなく、メッセージ優先度によって指定された位置にエンキューされます。 このようなキューを使用している間、処理されるメッセージの順序は、キューのアルゴリズムによって定義され、一般にFIFOではありません。

Akkaが他のアクターモデルの実装と異なる重要な機能は、現在の動作では常にデキューされた次のメッセージを処理しなければならず、次に一致するメールのためにメールボックスをスキャンする必要がないことです。 この振る舞いがオーバーライドされない限り、メッセージの処理に失敗することは決まって、失敗とみなされます。

子アクター

各アクターは、潜在的にスーパーバイザーです。サブタスクを委任するための子を作成すると、それが自動的に監督されます。 子のリストはアクターのコンテキスト内で管理され、アクターはそこにアクセスします。 リストへの変更は、子を作成する (context.actorOf(...)) か、停止する (context.stop(child)) ことによって行われ、これらのアクションは直ちに反映されます。 実際の作成および終了処理は、バックグラウンドで非同期で行われるため、スーパーバイザを「ブロック」しません。

スーパーバイザー戦略

アクターの最後の部分は、子供たちの障害を処理する戦略です。 障害制御はAkkaによって透過的に行われ、入ってくる障害ごとに スーパービジョン と モニタリング に記述されている戦略の1つを適用します。 この戦略は、アクターシステムがどのように構成されるかの基本であるため、アクターが作成されると変更することはできません。

それぞれのアクターに対してこのような戦略が1つしかないことを考慮すれば、これは、アクターの様々な子に異なる戦略が適用される場合、子は中間スーパーバイザーの下でマッチする戦略でグループ化されなければならないことを意味し、 タスクをサブタスクに分割することによるアクターシステムの構造化を必要とします。

アクターが終了すると

アクターが終了すると、例えば、再起動や自身の停止、スーパーバイザーに停止されたりすることによって制御されない方法で失敗しすると、リソースが解放され、メールボックスの残りすべてのメッセージがシステムの「デッドレターメールボックス」に排出されます。 それらを DeadLetter として EventStream に転送します。 メールボックスは、アクター参照内でシステムメールボックスに置き換えられ、すべての新しいメッセージを DeadLetter として EventStream にリダイレクトします。 これは最善の努力として行われますので、保証された配信を構築するために頼らないでください。

メッセージを静かに捨ててしまうだけの理由は、我々のテストによって触発されました。デッドレターが転送されるイベントバスに TestEventListener を登録し、受け取ったデッドレターごとに警告を記録します。これは、テストの失敗をより迅速に解読するのに非常に役立ちました。この機能は、他の目的にも使用できる可能性があります。

Contents