6

私は Play を初めて使用します。間違っている可能性があります。Play フレームワークは非同期でリクエストを処理することによりノンブロッキングであり、長時間のブロッキング操作は promise を使用して非同期で行う必要があります。では、特定のリクエストを処理するために promise またはマップされた promise を使用する必要があるのはいつですか?

たとえば、ユーザーがファイルをアップロードしたとします。ファイルがコントローラーに到達すると、そのファイルを一時フォルダーから目的のフォルダーに移動し、データベース レコードを挿入します。したがって、これには、ファイルの移動とデータベースへの挿入という 2 つのブロック操作が含まれます。ファイルが大きくなく、たとえば最大 10MB であると仮定すると、ファイルの移動は非常に高速になるはずです。また、データベース レコードの挿入も、ブロッキング データベース ドライバを使用すると高速になるはずです。

この単純なケースでは、1 つの promise/future を使用して 2 つの操作または 2 つのマップされた promise (ファイルを移動してから db レコードを挿入) を実行するか、promise をまったく使用しないでください。なぜ?

あなたの考え/経験を共有してください。前もって感謝します。

4

1 に答える 1

4

それは実際には紙一重であり、将来に何があり、何が将来にないかを決定することは、完全にアプリケーションに依存することになります。

一般に、将来のデータベース呼び出しについて心配する必要はありません。基になるドライバーがブロックしているため、フューチャーやアクターに入れても、どこかでブロックされます。そのため、データベースのレイテンシを減らしてみてください。データベースが (ネットワーク トポロジー的に言えば) 近くにあり、十分なリソースがあることを確認してください。

ファイルをブロックしない方法で移動することは、次のような方法でかなり簡単に処理できます。

def uploadFile() = Action {
  Async {
    // handle file moving
    Ok
  }
}

ただし、ファイルを処理するためにまだ 2 つのコストのかかる作業が残っているとします。1 つのアクションが他のアクションに依存している場合は、好きなように構成できます (1 つの Future で問題ありません)。2 番目のタスクを開始する前に、最初のタスクを完了する必要があります。ただし、このコードは 2 つの Future を使用したほうがクリーンかもしれません。高レベル、次のようなもの:

for { movedFile <- moveFile(file)
  analyzedFile <- analyzeFile(movedFile) } yield analyzedFile

私にはきれいに見えます。しかし、すべての小さなアクションを独自の Future に分割する必要があるとは思わないでください。

ただし、独立して実行できる 2 つのタスクがある場合は、2 つの Future を使用して両方を同時に実行できます。

于 2013-08-05T15:09:17.610 に答える