4

私は Akka と Scala には比較的慣れていませんが、Akka を汎用フレームワークとして使用して、さまざまな Web ツールや cli コマンドから情報を収集したいと考えています。

アクター モデルでは、アクターをブロックしないことが非常に望ましいという一般原則を理解しています。また、http リクエストの場合、非同期の http クライアント (Spray など) があります。これは、Actor フレームワーク内でリクエストを非同期に処理できることを意味します。

ただし、アクターを既存のブロッキング API 呼び出し (scala ProcessBuilder/ProcessIO ライブラリなど) と組み合わせる場合、どのようなアプローチが最適かはわかりません。これらの CLI コマンドの発行に関しては、比較的少量の並行性が予想されます。たとえば、12 コアのマシンで最大 10 の同時 CLI 呼び出しを実行するなどです。

単一のアクターがこれらの CLI コマンドを管理し、実際の作業を必要に応じて作成される Future に任せる方がよいでしょうか? それとも、PinnedDispatcher に支えられた別個のアクターのセットを維持するだけでよりクリーンになるでしょうか? または、他の何か?

4

1 に答える 1

4

Akka のドキュメント ( http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management ) から:

" ブロッキングには慎重な管理が必要

場合によっては、ブロッキング操作を行うことが避けられないことがあります。つまり、外部イベントが発生するのを待って、不確定な時間スレッドをスリープ状態にすることです。例としては、従来の RDBMS ドライバーまたはメッセージング API が挙げられます。通常、その (ネットワーク) I/O の根本的な理由は、内部で発生します。これに直面すると、ブロッキング呼び出しを Future 内にラップして、代わりにそれを使用したくなるかもしれませんが、この戦略は単純すぎます。アプリケーションの実行時にボトルネックを見つけたり、メモリやスレッドを使い果たしたりする可能性が非常に高くなります。増加した負荷の下。

「ブロッキングの問題」に対する適切な解決策の非網羅的なリストには、次の提案が含まれています。

  • アクター (またはルーター [Java、Scala] によって管理される一連のアクター) 内でブロッキング呼び出しを実行し、この目的専用または十分なサイズのスレッド プールを構成するようにします。
  • Future 内でブロッキング呼び出しを行い、任意の時点でのそのような呼び出しの数の上限を確保します (この性質の無制限の数のタスクを送信すると、メモリまたはスレッドの制限が使い果たされます)。
  • アプリケーションが実行されるハードウェアに適したスレッド数の上限をスレッド プールに提供して、Future 内でブロッキング呼び出しを行います。ブロッキング リソースのセット (複数のチャネルを駆動する NIO セレクターなど) を管理する単一のスレッドを専用にし、イベントが発生するとアクター メッセージとしてディスパッチします。

最初の可能性は、伝統的に一度に 1 つの未解決のクエリしか実行できず、内部同期を使用してこれを保証するデータベース ハンドルのような、本質的にシングル スレッドのリソースに特に適しています。一般的なパターンは、N 個のアクター用のルーターを作成することです。各アクターは単一の DB 接続をラップし、ルーターに送信されたクエリを処理します。次に、スループットが最大になるように数 N を調整する必要があります。これは、どの DBMS がどのハードウェアにデプロイされているかによって異なります。」

于 2012-10-16T13:31:51.467 に答える