web-dev-qa-db-ja.com

このWeb APIコントローラはなぜ同時ではないのですか?

内部に次のメソッドを持つWeb APIコントローラーがあります。

public string Tester()
{
    Thread.Sleep(2000);

    return "OK";
}

(Fiddlerを使用して)10回呼び出すと、約2秒後にすべての10回の呼び出しが返されることを期待しています。ただし、呼び出しはそれぞれ2、4、8 ... 20秒後に戻ります。同時に実行されないようにブロックしているものは何ですか?どうすれば修正できますか?

通常のコントローラーはweb-apiコントローラーと同じように動作しますか?

14
Elad Katz

説明した内容はASP.NETセッション状態のデフォルトの動作と一致し、web.configで無効にすることで解決できます。

ASP.NETセッション状態へのアクセスは、セッションごとに排他的です。つまり、2人の異なるユーザーが同時に要求を行うと、各個別のセッションへのアクセスが同時に許可されます。ただし、同じセッションに対して(同じSessionID値を使用して)2つの同時要求が行われた場合、最初の要求はセッション情報への排他的アクセスを取得します。 2番目の要求は、最初の要求が完了した後にのみ実行されます。 (最初の要求がロックのタイムアウトを超えたために情報の排他ロックが解放された場合、2番目のセッションもアクセスできます。)@ PageディレクティブのEnableSessionState値がReadOnlyに設定されている場合、読み取り専用の要求セッション情報によって、セッションデータが排他的にロックされることはありません。ただし、セッションデータの読み取り専用要求は、セッションデータの読み取り/書き込み要求によって設定されたロックがクリアされるまで待機する必要がある場合があります。

ソース: ASP.NETセッション状態の概要

18
sisve

私はあなたの質問に答えているとは思いませんが、ここに書きたいのはコメントには大きすぎます。

まず、ASP.NET Web APIはセッション状態とは何の関係もありません。実際、セッションをWeb APIで使用する必要がある場合は、明示的に有効にする必要があります。

さて、私はあなたと同じまったく同じAPIコントローラーを持っており、IISでホストしています。同時リクエストを行うと、リクエストはシリアルではなくパラレルで実行されます。これが私がFiddlerからテストした方法です。

最初に、APIに対してGETを実行し、200のステータスコードを待機しました(Fiddlerの左側のペインの#1)。次に、1番を選択してUを押し、同じリクエストを無条件に9回再生しました。これで、左側のペインに10個のリクエストがあります(#1から#10)。次に、それらの10個すべてを選択し、Rを押して、10個すべての要求を並行して再発行しました。次に、左側のペインでリクエスト11〜20を選択し、[タイムライン]タブに移動しました。このグラフが見えます。

PS。ところで、ローカルで実行されているWeb APIをテストしました。

enter image description here

次に、アクションメソッドが受け取ったタイムスタンプ要求をログに記録したいと思いました。そこで、このような文字列を返すようにアクションメソッドを変更しました。

public string Get()
{
    string ts = DateTime.Now.ToString("mm:ss.fff");
    Thread.Sleep(2000);
    return ts;
}

次のものを手に入れました。

00:43.795
00:43.795
00:45.812
00:44.517
00:43.795
00:43.795
00:45.515
00:43.795
00:43.795
00:43.795

つまり、すべてのリクエストが並行して実行されています。

8
Badri

あなたの問題に関連するこの質問を見てください: すべてのWebリクエストが並行して実行され、非同期で処理されますか?

それはそれを述べています:

デフォルトでは、webApiサービスはすべての受信リクエストを並行して実行しますが、現在の複数のリクエスト(ある時点での)が異なるセッションからのものである場合に限られます。つまり、単一のクライアントが同時にいくつかのリクエストをサーバーに送信する場合、それらのすべてが順次実行され、同時に実行されることはありません。

これを解決するために、 here で説明されているように、非同期メソッドを使用できます。

通常、次のように、メソッドを非同期として宣言する必要があります。

public async Task<MyObj> GetObj()
5
Mark Segal

Web APIのどこかでSession Stateを有効にしておく必要があります。 Web APIはデフォルトで静止しており、セッションはありません。 global.asax Application_AuthenticateRequestセクションを確認します(ここで、Web APIのセッション状態を有効にします)。セッション状態を有効にした場所を見つけ、それを読み取り専用モードに設定して、セッション状態を使用するWebメソッドの並列処理を可能にします。同様のこの質問を参照してください: Web APIサービス-サーバーで同時に実行される要求を作成する方法

このようなものを探してください:

HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);

これを次のように変更します。

HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
1

代わりにこれを使ってみてください:

public async Task<string> Tester()
{

    await Task.Delay(2000);
    return "OK";
}

これを参照して、ブロックするTask.DelayとThread.Sleepの違いを確認してください http://social.technet.Microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs- task-delay.aspx

0
Omar.Alani