3

Joe Armstrong の論文から、彼はアクター ベースのプログラムは次の 3 つの手順で設計する必要があると指定しました。問題は、ステップが実際の問題にどのように対応するか、またはそれらをどのように適用するかを理解していないことです。これがジョーの最初の提案です。

  1. 私たちは、現実世界の活動において、すべての真に同時の活動を識別します。
  2. 並行アクティビティ間のすべてのメッセージ チャネルを識別します。
  3. さまざまなメッセージ チャネルを流れるすべてのメッセージを書き留めます。それではプログラムを書いていきます。プログラムの構造は、問題の構造に正確に従っている必要があります。現実世界の各並行アクティビティは、プログラミング言語で正確に 1 つの並行プロセスにマップする必要があります。問題がプログラムに 1 対 1 でマッピングされている場合、そのプログラムは問題と同型であると言えます。

マッピングが正確に 1:1 であることが非常に重要です。その理由は、問題と解決策の間の概念的なギャップを最小限に抑えるためです。このマッピングが 1:1 でない場合、プログラムはすぐに劣化し、理解しにくくなります。この縮退は、CO 以外の言語を使用して並行問題を解決する場合によく見られます。多くの場合、プログラムを機能させる唯一の方法は、いくつかの独立したアクティビティを同じ言語スレッドまたはプロセスで制御することです。これにより、不可避的に明瞭さが失われ、プログラムが複雑で再現不可能な干渉エラーにさらされることになります。

1番は割とわかりやすいと思います。私が迷子になるのは#2(および3)です。私の欲求不満を説明するために、この要旨で利用可能な小さなサービスをスタブ化しました (コールバックを備えた Ruby サービス)。

そのサンプル サービスを見ると、#1 の答えがわかります。5つの同時サービスがあります。

  1. 始める
  2. ログインゲートウェイ
  3. ログアウトゲートウェイ
  4. 止まる
  5. 申し込む

これらのサービスの一部は、サービスの状態によっては機能しません (または機能しないはずです)。サービスが開始されていない場合、ログイン/ログアウト/購読は意味がありません。この種の状態情報は、Joe の 3 つのステップに関連していますか?

とにかく、その要旨のサンプル/モック サービスを考えると、誰かがこのサービスを Actory の方法でラップするプログラムをどのように設計するのか疑問に思っています。Joe の 3 つのステップを適用する方法に関するガイドラインのリストを確認したいと思います。いくつかのコード (任意の言語) を書くためのボーナス ポイント。

4

1 に答える 1

9

一般に、アクターを使用するようにアプリケーションを構築する場合、アプリケーションの並行機能を特定する必要がありますが、これを理解するのは難しい場合があります。5 つの同時「サービス」を識別します。

  1. 始める
  2. ログインゲートウェイ
  3. ログアウトゲートウェイ
  4. 止まる
  5. 申し込む

1、4、および 5 は、システムを介して流れるメッセージのタイプのようです。2 および 3 は、どのように説明すればよいかわかりません。あなたの要点はかなり大きく、私にはあまり明確ではありませんが、ある種のメッセージキューシステムを持っているようです. ユーザーが実行できるアクションは次のとおりです。

  1. システムにログインする
  2. システムからログアウトする
  3. メッセージのキューを購読する

ログインとログアウトには認証手順が必要だと思います。さらに、ユーザーが認証ステップに失敗した場合、接続は切断されますが、接続を作成するだけでは十分な認証ではないと想定します。

システムが実行するアクションは次のとおりです。

  1. ユーザーアクションの処理
  2. メッセージをキューのサブスクライバーにルーティングする

それが広く真実でない場合は、お知らせください。この回答を変更します。(ユーザーに送信されるメッセージはユーザーによって生成されたものではなく、 Systemの本質的な部分であると仮定します。おそらく、監視サービスについて話しているのかもしれません。) とにかく、ここで並行とは何ですか? いくつかのこと:

  1. ユーザーは互いに独立して行動します
  2. キューには個別の状態があります

アクター ベースのアーキテクチャは、各同時実行エンティティを独自のプロセスとして表します。ユーザーは、認証、キューへのサブスクライブ、メッセージの受信、さらに多くのキューへのサブスクライブを行い、最終的に切断する有限状態マシンです。Erlang/OTP では、これをgen_fsmで表します。Userプロセスは、クライアントと対話するために必要なすべての状態を保持します。これは、ネットワーク経由でサービスを公開している場合、ソケットになります。

認証は、システム自体が「プロセス」であることを意味しますが、Erlang/OTP ではアプリケーションと呼ばれるプロセスの集まりである可能性が高いです。余談です。簡単にするために、 System自体が、適切に定義されたプロトコルと、ユーザー資格情報を保持する状態を持つ単一のプロセスであると仮定します。したがって、ユーザーログインは、ユーザー プロセスからシステム プロセスへの明確に定義されたメッセージそこから応答です。認証がなければ、ユーザーに関連する唯一の状態はソケットであるため、システムプロセスは必要ありません。

注意深い読者は、各Userのソケット接続をどこで受け入れるのかと尋ねるでしょう。ああ、良い質問です。言及されていない別の並行エンティティがあり、ここではListenerと呼びます。これは、接続をリッスンするだけの別のプロセスであり、新しく確立されたソケットごとにユーザーを作成し、所有権を新しいユーザープロセスに渡し、ループてリッスンします。

Queueは有限状態マシンでもあります。開始状態から、明確に定義されたプロトコルを介してユーザーのサブスクリプション要求を受け入れ、メッセージをサブスクライバーにブロードキャストするか、ユーザープロセスからのサブスクライブ解除要求を受け入れます。これは、QueueがUserプロセスの内部ストアを持っていることを意味します。その詳細は、言語とニーズに大きく依存します。たとえば、Erlang/OTP では、各キュープロセスはgen_serverであり、ユーザープロセス ID (または PID) をリストに格納し、各メッセージを送信するために、リスト内の各ユーザープロセスに単純に複数送信します。

(Erlang/OTP では、ユーザー スーパーバイザーを使用して、プロセスが存続し、終了時に再起動されるようにします。これにより、アクター ベースのアーキテクチャで信頼性を確保するために Erlang 開発者が行う必要のある作業量が大幅に簡素化されます。)

基本的に、ジョーが書いたことを言い換えると、アクター ベースのアーキテクチャは次の点に要約されます。

  • システム内の同時実行エンティティを識別し、プロセスによる実装でそれらを表します。
  • プロセスがメッセージを送信する方法を決定します (Erlang/OTP ではプリミティブな操作ですが、C または Ruby では明示的に実装する必要があります)。
  • 状態の変更を隠す、システム内のエンティティの明確に定義されたプロトコルを作成します。

インターネットは、世界で最も成功したアクター ベースのアーキテクチャであると言われてきましたが、実際にはそう遠くありません。

于 2013-08-22T05:46:10.433 に答える