web-dev-qa-db-ja.com

アクターとフューチャーを使用するのはいつですか?

私は現在Playに取り組んでいます!次のアーキテクチャを持つプロジェクト:

コントローラー->サービス(アクター)->モデル(通常のケースクラス)

入ってくるリクエストごとに、次のようにサービスレイヤーを呼び出します。

Service ? DoSomething(request, context)

アプリの初期化中に作成され、オンデマンドで拡張可能なakkaルーターの背後に、これらのサービスアクターが設定されています。

また、サービスでは、ほとんどの場合、適度なデータ操作またはデータベース呼び出しを行います。

receive = {
    case DoSomething(x, y) => {
           ...
           Model.doSometing(...)
           sender ! result
    }
}

サービスにアクターを使用するべきか、それともFuturesのみを使用するべきかについて、私は考え直しています。

  1. サービスアクターで変更する必要がある内部状態はありません。受信したメッセージはすべて関数に送られ、結果が出力されます。これは俳優モデルの大きな強みではありませんか?

  2. 私たちは俳優モデルからかなり離れているように見える多くの仕事をしています

  3. 大量の計算は行っていません。リモート処理はほとんどの場合データベース用であり、リモートアクターへのラウンドトリップを行って一部のdb呼び出しを行う必要がないため、意味がありません。

  4. 私たちはactivemongoを使用しているので、すべてのdb呼び出しは非ブロッキングです。私たちはこれらの電話をたくさんかけることができます

Akkaを削除してFuturesを使用するだけで私たちの生活はずっと簡単になり、何も失うことはないように思えます。

32
James Cowhen

俳優とすべきものとすべきでないことについての話題については、確かに意見の不足はありません。次の2つの投稿のように:

http://noelwelsh.com/programming/2013/03/04/why-i-dont-like-akka-actors/

http://www.chrisstucchio.com/blog/2013/actors_vs_futures.html

あなたがこの質問に対する絶対的な答えを見つけるのは、それが状況的なものであり、それがあなたの好みとあなたの問題次第だとは思わないでしょう。私があなたにできることは、私たちがAkkaを約2年間実装したことに基づいた私の意見を述べることです。

私にとって、私はAkkaを本当にプラットフォームとして考えるのが好きです。私たちはアクターモデルを採用しましたが、クラスタリング/リモーティング、FSM、ルーティング、サーキットブレーカ、スロットリングなど、プラットフォームが提供する他のすべての良さを維持しています。私たちは、SOAのようなアーキテクチャーを、サービスとして機能するアクターで構築しようとしています。これらのサービスをクラスター全体にデプロイしているため、ロケーションの透過性やルーティングなどを利用して、機能を提供しています。サービスコンシューマー(それ自体が別のサービスである可能性があります)が、サービスが展開されている場所に関係なく、高可用性の方法でサービスを見つけて使用できるようにします。Akkaは、提供するプラットフォームツールに基づいて、このプロセス全体をかなり簡単にします。

私たちのシステムには、私が財団サービスと呼ぶものの概念があります。これらは本当にシンプルなサービスです(特定のエンティティの基本的な検索/管理サービスなど)。これらのサービスは通常、他のサービスを呼び出さず、場合によっては、DBルックアップを実行するだけです。これらのサービスはプールされ(ルーター)、通常は状態がありません。それらはあなたがあなたのサービスの一部であるとあなたが説明しているものとかなり似ています。次に、これらの基礎サービスに加えて、ますます複雑なサービスの構築を開始します。これらのサービスのほとんどは短期間で(質問を避けるため)、場合によってはFSMベースであり、基礎サービスからデータを収集し、結果として処理を実行します。これらのファウンデーションサービス自体は非常に単純で、アクターを必要としないという人もいますが、より高いレベルのサービスにそれらを構成すると、それらを検索してどこにでも置くことができるという柔軟性が好きです(場所透過)使用可能なインスタンス(ルーティング)がいくつでもあるクラスター内。

したがって、私たちにとっては、そのサービスがどんなに単純であっても、クラスター内で他のサービスによる消費のために利用できる一種のマイクロライクなサービスとしてアクターをベースラインとすることが設計上の決定でした。私はこれらのサービスと、どこにいても、非同期の粗いインターフェースを介して通信するのが好きです。これらの原則の多くは、優れたSOAを構築するための側面です。それがあなたの目標であれば、Akkaはその目標を達成するのに非常に役立ちます。あなたがそのようなことをすることを望んでいないなら、多分あなたはあなたのサービスのためにAkkaを使うことのあなたの決定を疑うことは正しいでしょう。先に述べたように、アーキテクチャの観点から何をしようとしているのかを理解し、それらの目標を満たすようにサービス層を設計するのは、実際にあなた次第です。

31
cmbaxter

私はあなたが正しい軌道に乗っていると思います。

サービスアクターで変更する必要がある内部状態はありません。受信したメッセージはすべて関数に送られ、結果が出力されます。これは俳優モデルの大きな強みではありませんか?

私はChris Stucchioのブログ(上記の@cmbaxterで参照されている)をすぐに見つけました。私の場合は非常に単純だったので、構造上の考慮事項は有効なポイントではありませんでした。ちょうどあなたが持っているように、ルーティングと大量のデータベースアクセスをスプレーしてください。状態なし。したがって未来。とてもシンプルなコード。

8
akauppi

私は同じことを考えていて、データアクセスにAkkaを使用することを決定しました。これは非常にうまく機能し、非常にテスト可能(そしてテスト済み)で、非常に移植可能です。

私たちは、アプリでブートストラップしたリポジトリ、長命の俳優を作成しました:(参考までに、DB Accessにはスリックを使用していますが、MongoDBのニーズにも同様のデザインを使用しています)

val subscriptionRepo = context.actorOf(Props(new SubscriptionRepository(appConfig.db)), "repository-subscription")

これで、データの「リクエスト」メッセージを送信できるようになりました。例:

ケースクラスSubscriptionsRequested(atDate:ZeroMillisDateTime)

俳優が応答すること

case class SubscriptionsFound(users: Seq[UserSubscription])

または失敗(例外)

私たちの状況(スプレーアプリだけでなくCLIも)では、これらの呼び出しを短いリビングアクターで囲み、コンテキストを受け取り、受付で完了し、終了します。 (これらのアクターでドメイン固有のロジックを処理し、ライフサイクルと例外を管理する別のアクターを拡張する必要があるので、必要に応じて部分的な関数を指定し、タイムアウト、一般的な例外などを処理する抽象アクターを残すだけで済みます。

また、開始アクターで実行する必要がある追加の作業が必要な状況もあり、xメッセージをリポジトリに発射し、アクターがそれらのメッセージを到着時に格納し、到着したら何かを実行して、送信者への完了(たとえば)とそれ自体のクローズ。

この設計のおかげで、アプリの外部に非常に反応性の高いリポジトリがあり、Akka TestKitとH2で完全にテストされ、完全にDBに依存せず、DBからデータにアクセスするのは非常に簡単です(そして、ASKを実行することはなく、Tellのみ: repoに伝える、送信者に伝える、完了、またはx reposに伝え、完了までの予想される結果をパターンマッチさせ、送信者に伝える)。

0
David Puleri

状態を変更する非常に長い生き物が必要な場合は、俳優をクレートする必要があります。他の場合では、俳優、特に型付けされていない俳優からの利益はありません。 -毎回パターンマッチングを行う-アクターのライフサイクルを制御する-スレッド間で渡すべきではないものを覚えておくアクターが非常によく合うタスクがありますが、どこにでもあるわけではありません

0
Igor Yudnikov