web-dev-qa-db-ja.com

ASP.NET MVCで非同期コントローラを使用するタイミング

私は、ASP.NET MVCで非同期アクションを使用することについていくつか懸念があります。それがいつ私のアプリのパフォーマンスを向上させるのですか?そしていつしないのですか

  1. ASP.NET MVCのどこでも非同期アクションを使用するのは良いことですか。
  2. 適切な方法について:データベースに問い合わせをしたいときに(EF/NHibernate /他のORMを介して)async/awaitキーワードを使用しますか?
  3. 1つの単一アクションメソッドで、データベースを非同期的に照会するためにawaitキーワードを何回使用できますか?
191
Vnuuk

非同期アクションメソッドは、アクションが複数の独立した長時間実行操作を実行する必要がある場合に役立ちます。

AsyncControllerクラスの一般的な用途は、長時間実行されるWebサービス呼び出しです。

私のデータベース呼び出しは非同期であるべきですか?

IISスレッドプールは、データベースサーバーよりも多くの同時ブロッキング要求を処理できます。データベースがボトルネックになっている場合は、非同期呼び出しによってデータベースの応答が速くなることはありません。スロットルメカニズムがないと、非同期呼び出しを使用して、圧倒されているデータベースサーバーにより多くの作業を効率的にディスパッチするだけで、より多くの負担がデータベースに移されます。あなたのDBがボトルネックになっているなら、非同期呼び出しは魔法の弾丸にはなりません。

あなた12 referencesを見てください

@PanagiotisKanavosのコメントに由来する:

さらに、非同期とは並列という意味ではありません。非同期実行によって、貴重なスレッドプールスレッドが外部リソースをブロックする必要がなくなります。複雑さやパフォーマンス上のコストはかかりません。これは、同じIISマシンがより多くの同時要求を処理できることを意味します。高速に実行されるわけではありません。

ブロッキング呼び出しはCPU集中型のスピンウェイトで始まることも考慮する必要があります。ストレスの多い時間帯に通話をブロックすると、遅延が増大し、アプリプールがリサイクルされます。非同期呼び出しは単にこれを避けます

94
Tharif

あなたは私の このテーマに関するMSDN記事が役立つ ;を見つけるかもしれません。その記事では、ASP.NETでasyncを使用するのにhowだけでなく、ASP.NETでasyncを使用するwhen youを説明する多くのスペースを取りました。

ASP.NET MVCで非同期アクションを使用することには懸念があります。アプリのパフォーマンスが向上する場合と、そうでない場合。

最初に、async/awaitがすべてスレッドの解放であることを理解してください。 GUIアプリケーションでは、主にGUIスレッドを解放するであるため、ユーザーエクスペリエンスが向上します。サーバーアプリケーション(ASP.NET MVCを含む)では、主にリクエストスレッドを解放するであるため、サーバーを拡張できます。

特に、wo n't:

  • 個々のリクエストをより速く完了させます。実際、それらは(ほんの少しだけ)遅くなります。
  • awaitにヒットしたら、呼び出し元/ブラウザーに戻ります。 awaitは、ブラウザではなく、ASP.NETスレッドプールにのみ「譲り渡し」ます。

最初の質問は-ASP.NET MVCのすべての場所で非同期アクションを使用するのは良いですか?

I/Oを行うすべての場所で使用するのが良いと思います。ただし、必ずしもbeneficialとは限りません(以下を参照)。

ただし、CPUにバインドされたメソッドに使用するのはbadです。開発者は、コントローラでTask.Runを呼び出すだけでasyncのメリットを享受できると考えることがありますが、これはひどい考えです。そのコードは別のスレッドを取得することでリクエストスレッドを解放するため、まったく利点がありません(実際、追加のスレッドスイッチのペナルティを受けています)。

(EF/NHibernate /他のORMを介して)データベースにクエリする場合、async/awaitキーワードを使用しますか?

使用可能な待機メソッドを使用できます。現在、ほとんどの主要なプレーヤーはasyncをサポートしていますが、サポートしていないものもいくつかあります。 ORMがasyncをサポートしていない場合、Task.Runまたはそのようなものでラップしようとしないでください(上記を参照)。

「あなたcoulduse」と言ったことに注意してください。単一のデータベースバックエンドを備えたASP.NET MVCについて話している場合、(ほぼ確実に)asyncからスケーラビリティの利点を得ることはできません。これは、IISがSQLサーバー(または他の従来のRDBMS)の単一インスタンスよりもはるかに多くの同時要求を処理できるためです。ただし、バックエンド(SQLサーバークラスター、Azure SQL、NoSQLなど)がより近代的であり、バックエンドがスケーリング可能であり、スケーラビリティのボトルネックがIISである場合、thenスケーラビリティの利点を得ることができますasyncから。

3番目の質問-awaitキーワードを使用して、1つのアクションメソッドでデータベースを非同期にクエリできる回数

好きなだけ。ただし、多くのORMには接続ごとに1つの操作ルールがあることに注意してください。特に、EFはDbContextごとに1つの操作のみを許可します。これは、操作が同期か非同期かに関係なく当てはまります。

また、バックエンドのスケーラビリティにも注意してください。 SQL Serverの単一のインスタンスにアクセスしていて、IISが既にSQLServerをフルキャパシティに維持できる場合、SQLServerへのプレッシャーを2倍または3倍にすることはまったく役に立ちません。

214
Stephen Cleary

aSP.NET MVCのどこでも非同期アクションを使用するのは良いことですか。

プログラミングではいつものように、dependsです。ある道を進むときには常にトレードオフがあります。

async-awaitはあなたがあなたのサービスへの同時リクエストを受けていることがわかっていて、あなたがスケールアウトにできるようにしたいと思う場所で輝いています。 async-awaitはスケールアウトにどのように役立ちますか?ネットワーク呼び出しやデータベースへのアクセスなど、async IO callsynchronouslyを呼び出すと、現在のスレッドが原因となります。実行は要求が終了するのを待ってブロックされます。 async-awaitを使用すると、IO呼び出しが完了した後も、中断したところからメソッドが実行を続けるように、フレームワークでステートマシンを自動的に作成できます。

注意すべきことは、このステートマシンにはわずかなオーバーヘッドがあるということです。メソッドを非同期にしても実行が速くなることはありません。これは理解する重要な要素であり、多くの人が誤解しています。

async-awaitを使用するときに考慮すべきもう1つのことは、それがasync all-wayであるという事実です。これは、非同期が呼び出しスタック全体に浸透することを意味します。 。つまり、同期APIを公開する場合は、 asyncsync のように、一定量のコードを複製することがよくあります。あまり混ぜないでください。

(EF/NHibernate /他のORMを介して)データベースにクエリを実行するときに、async/awaitキーワードを使用しますか。

最近のデータベースプロバイダではTAP(Task Asynchronous Pattern)を実装した非同期メソッドを公開しているため、async IO呼び出しを使用することを選択した場合はasync-awaitが適しています。

1回のアクションで、待機キーワードを使用してデータベースに非同期的に問い合わせることができる回数

データベースプロバイダによって規定された規則に従う限り、必要なだけの数。あなたが作ることができる非同期呼び出しの量に制限はありません。互いに独立したクエリを同時に実行できる場合は、それぞれに対して新しいタスクを実行し、await Task.WhenAllを使用して両方のタスクが完了するのを待ちます。

19
Yuval Itzchakov

私の5セント:

  1. DBまたは外部サービスWebサービスのようにIO操作を行う場合に限り、async/awaitを使用してください。
  2. 常にDBへの非同期呼び出しを優先します。
  3. 毎回DBに問い合わせます。

P.Sポイント1には例外的なケースがありますが、これについては非同期の内部構造について十分に理解しておく必要があります。

追加の利点として、必要に応じてIO呼び出しを並行して行うことができます。

Task task1 = FooAsync(); // launch it, but don't wait for result
Task task2 = BarAsync(); // launch bar; now both foo and bar are running
await Task.WhenAll(task1, task2); // this is better in regard to exception handling
// use task1.Result, task2.Result
7

asyncアクションは、要求がDBまたはネットワークバインド呼び出しに対して何らかのI/O操作を実行し、要求したスレッドが、直前に呼び出したDB呼び出しまたはネットワークバインド呼び出しから応答が得られる前に停止する場合に最適です。これを使用するのが最善です。実際にはアプリケーションの応答性が向上します(DBやそのような他の操作を待機している間にASP input\outputスレッドが少なくなるため)。私のすべてのアプリケーションでは、DBを何度も呼び出す必要があるたびに、常にそれらをawaiatableメソッドでラップし、それをawaitキーワードで呼び出しました。

6
Dimitri

ご存じのとおり、MVCは非同期コントローラをサポートしているので、それを利用する必要があります。コントローラが時間のかかる操作(ディスクベースのI/Oまたは他のリモートサービスへのネットワークコール)を実行する場合、要求が同期的に処理されていれば、IISスレッドはビジーです。ずっと。その結果、スレッドは時間のかかる操作が完了するのを待っているだけです。最初に要求された操作が進行中の間に他の要求を処理することによって、よりよく利用することができます。これはより多くの同時リクエストを処理するのに役立ちます。あなたのWebサービスは非常にスケーラブルで、簡単には C10k問題に遭遇しません 。 dbクエリにはasync/awaitを使用することをお勧めします。そしてはい、あなたはあなたが適当と考えるのと同じくらい多くの回数それらを使うことができます。

ここで 見てください 優れたアドバイスを得ます。

4
anurag

ASP.NET MVCのどこでも非同期アクションを使用するのは良いことですか。

特に大量のデータや計算操作で発生するワーカープロセスレベルでパフォーマンスの問題がある場合は、非同期メソッドを使用できる場合はいつでもそうすることをお勧めします。そうでなければ、単体テストはキャストが必要になるので必要ありません。

適切な方法について:データベースに問い合わせをしたいときに(EF/NHibernate /他のORMを介して)async/awaitキーワードを使用しますか?

はい、できればワーカープロセスのレベルでパフォーマンスの問題を回避するために、できるだけすべてのDB操作に非同期を使用することをお勧めします。 EFは、ほとんどの操作に対して、次のような多くの非同期の選択肢を作成しています。

.ToListAsync()
.FirstOrDefaultAsync()
.SaveChangesAsync()
.FindAsync()

Awaitキーワードを使用して、1つのアクションメソッドでデータベースに非同期的に問い合わせることができる回数

空が限界

2
Shadi Namrouti

私の経験では、今日、多くの開発者がasync/awaitをコントローラーのデフォルトとして使用しています。

私の提案は、あなたがそれがあなたを助けると知っているときだけ使用することです

その理由は、 Stephen Cleary および他の既に述べたように、パフォーマンスの問題を解決するのではなく、導入することができ、特定のシナリオでのみ役立ちます:

  • 高トラフィックコントローラー
  • スケーラブルなバックエンド
1
gajama