2016-06-13 23 views
4

私は既存のC#ASP.NET MVC Webアプリケーションを使用していますが、非同期を作成するかどうかを決定できない機能を追加しています。コントローラメソッドを非同期にするか、同期させますか?

今のところ、アプリケーションのホームページではページが処理され、ユーザーがログインします。それ以上のことは何も起こりません。

ホームページにアクセスしたときに識別子を取得し、ホームページのHTMLタグに返すデータベースを呼び出しているWeb APIの呼び出しを生成する機能を追加しています。この識別子は、ソース/ HTMLビューでのみ表示されます(さまざまな内部トラッキングの目的で追加されています)。

Web API /データベース呼び出しは単純で、識別子を取得してコントローラに返すだけです。それにもかかわらず、私はアプリがこの呼び出しを非同期的に行うべきかどうか疑問に思っています。ウェブサイトのトラフィックは膨大ではありませんが、私はまだ並行性、パフォーマンス、将来のスケーラビリティについて疑問を抱いています。

私がActionMethod全体を非同期にしなければならないということは、その影響がどのようなものか分かりません。現時点で同期パターンの基本パターンは次のとおりです。

public ActionResult Index() 
    { 
     var result = GetID(); 

     ViewBag.result = result.Data; 

     return View(); 
    } 

    public JsonResult GetID() 
    { 
     var result = ""; 
     var url = "http://APIURL/GetID"; 

     using (WebClient client = new WebClient()) 
     { 
      result = client.DownloadString(url); 
     } 

     return Json(result, JsonRequestBehavior.AllowGet); 

    } 

+1

async/awaitキーワードを使用できる場合は、常にasyncを使用してください。レガシーパターンを使用する必要がある場合は、現在のスケーリングの問題がないかぎり、それを使用しないでください。これは、獲得したレベルを超えて複雑さのレベルを上げます。 – MatthewMartin

答えて

2

ここで、async IOを使用する理由は、同時に多くのスレッドを実行しないことです。スレッドは、OSリソースとメモリを消費します。スレッドプールはまた、突然の負荷に合わせるのに少し遅くなります。ウェブアプリのスレッド数が100を下回り、負荷が極端に高くない場合は、心配する必要はありません。

一般的に、Webサービスが遅くなるほど、より多くの場合、より有益な非同期IOと呼ばれることがあります。実行中のスレッド(平均待ち時間)が必要です。したがって、100msの通話時間と10回の通話は平均で約1スレッドです。

数字を実行して、何かを変更する必要があるかどうかを確認します。

0

まずは、Webアプリケーションのコンテキストで、非同期の目的を実現してください。 Webサーバーには、スレッドプールと呼ばれるものがあります。一般的に言えば、1スレッド== 1リクエストなので、プールに1000スレッド(標準)がある場合、あなたのウェブサイトはおおよそ1000の同時リクエストを処理できます。また、1つのリソースをレンダリングするために多くの要求がかかることがあります。 HTML文書自体は1つの要求ですが、各画像、JSファイル、CSSファイルなども要求です。次に、ページが発行するAJAXリクエストがあります。言い換えれば、単一のリソースに対する要求がWebサーバーへの20以上の要求を生成することは珍しいことではありません。

サーバが最大リクエスト(すべてのスレッドが利用されている)に達すると、それ以上のリクエストはスレッドが利用可能になるとキューに入れられ、処理されます。非同期が行うことは、いくつかの追加のヘッドルームを購入することです。待ち状態にあるスレッド(データベースクエリの結果、Webサービスからの応答、ファイルシステムから読み込まれるファイルなど)を待っている場合、asyncはこれらのスレッドをそこでは、待機中のリクエストのいくつかをフィールドすることができます。スレッドが完了するのを待っていたときに、その要求の処理を終了するために新しいスレッドが要求されます。

ここで注意すべき重要な点は、新しいスレッドがであり、リクエストのサービスを完了するためにが要求されたことです。スレッドがプールに解放されたら、まったく新しい要求のように、スレッドを再び待つ必要があります。これは、プール内のスレッドの可用性に応じて、実行中の同期よりもが長くてもを実行することがあることを意味します。また、非同期的な冗長性により、全体的なロード時間も増加します。

非同期!=高速です。多くの場合、は遅いになることがありますが、Webサーバーがリソースをより効率的に利用できるようになります。これは、下降と正常な負荷の違いを意味します。このため、「すべてを非同期にする必要がありますか?」という質問には、普遍的な答えはありません。非同期は、生のパフォーマンスと効率のトレードオフです。場合によっては、非同期を使用するのは意味がないかもしれませんが、他の場合は、それを適用できるすべてのものに使用したいかもしれません。あなたがする必要があるのは、アプリケーションのストレスポイントを最初に特定することです。たとえば、データベースインスタンスがWebサーバーと同じサーバー上に存在する場合(良い考えではありません)、データベース照会でasyncを使用するとかなり無意味です。待ち時間の主な原因はネットワーク待ち時間ですが、ファイルシステムへのアクセスは通常比較的早いです。一方、データベースサーバーがリモートデータセンターにあり、そこからWebサーバーまでのパイプを移動するだけでなく、横断するファイアウォールなどの処理を行う必要がある場合は、ネットワークの待ち時間がはるかに重要であり、asyncはおそらく非常に良い考えです。

あなたの設定、環境、アプリケーションのニーズを評価する必要があります。そして、それだけで、これについて賢明な決定をすることができます。つまり、たとえ非同期のオーバーヘッドがあっても、ネットワークレイテンシが関与していれば、asyncを使用するのはかなり安全です。注意を払う場所を誤っていて、どこでも非同期を使用するだけで問題はありません。パフォーマンスを最適化しようとしているのであれば(おそらく次のFacebookを開始していますか?)、もっと賢明なものにしたいと思っています。

1

はい、たくさんの考えがありますが、それだけでは答えにはなりません。 ;)


コンテキストがあまりないため、本当に良い答えはありません。しかし、私たちが知っていることに対処しましょう。

  1. 私たちはWebアプリケーションであるため、リクエスト/応答の各サイクルはパフォーマンスに直接影響を与え、ボトルネックになる可能性があります。
  2. 私たちは私たちが内部的に別のAPI呼び出しを呼び出すので、同じサーバー上でホストされていると仮定すべきではありません。すべてのI/Oバインド操作と同じように処理する必要があります。

上記の2つの既知の要因を考慮して、asyncに電話する必要があります。次の点を考慮

public async Task<ActionResult> Index() 
{ 
    var result = await GetIdAsync(); 

    ViewBag.result = result.Data; 

    return View(); 
} 

public async Task<JsonResult> GetIdAsync() 
{ 
    var result = ""; 
    var url = "http://APIURL/GetID"; 

    using (WebClient client = new WebClient()) 
    { 
     // Note the API change here? 
     result = await client.DownloadStringAsync(url); 
    } 

    return Json(result, JsonRequestBehavior.AllowGet); 
} 

を今、私たちは、正しくごTask<T>帰国事業でasyncawaitキーワードを使用しています。理想的なパフォーマンスを確保するのに役立ちます。 client.DownloadStringAsyncのAPIの変更にも注意してください。これは非常に重要です。

関連する問題