3

最近、ASP.NET MVC3 コントローラーの 1 つにいくつかの (かなり些細な) 変更を加え、アクションの 1 つを非同期アクションに変更しました。基本的に、次のようなコードを取りました。

public ActionResult MyAction(BindingObject params){
    // use HttpWebRequest to call an external API and process the results
}

そして、それを次のようなコードに変換しました。

private delegate ActionResult DoMyAction(BindingObject params);

public void MyActionAsync(BindingObject params){
    AsyncManager.OutstandingOperations.Increment();
    var doMyAction = new DoMyAction(MyAction);
    doMyAction.BeginInvoke(params, MyActionCallback, doMyAction);
}

private void MyActionCallback(IAsyncResult ar){
    var doMyAction = ar.AsyncState as DoMyAction;
    AsyncManager.Parameters["result"] = doMyAction != null ? doMyAction.EndInvoke(ar) : null;
    AsyncManager.OutstandingOperations.Decrement();
}

public ActionResult MyActionCompleted(ActionResult result){
    return result;
}

private ActionResult MyAction(BindingObject params){
    // use HttpWebRequest to call an external API and process the results
}

MyAction を呼び出してローカルでテストすると、期待どおりに各メソッドのブレークポイントが起動し、最終的に期待される結果が返されます。

HttpWebRequest が外部 API を呼び出すのを待ってワーカー スレッドが消費されず、最悪の場合、まったく効果がないため、この変更により高負荷時のパフォーマンスが向上すると予想されます。

この変更をプッシュする前は、サーバーの CPU 使用率は平均 30% 前後で、W3SVC_W3WP Active Requests perfmon 統計は 10 ~ 15 前後で推移していました。サーバーは Win Server 2008 R2 で、MVC サイトは 1 秒あたり約 50 の要求を取得します。

この変更をプッシュすると、CPU は一定の 90 ~ 100% の使用率まで上昇し、W3SVC_W3WP Active Requests カウンターは、最大値の 5000 に達してそこに留まるまでゆっくりと増加します。Web サイトが完全に応答しなくなります (タイムアウトするか、「サービスを利用できません」というエラーが発生します)。

私の仮定は、AsyncController を正しく実装していないか、必要な追加の構成が欠落しているか、AsyncController の使用目的を誤解しているだけです。いずれにせよ、私の質問は、なぜこれが起こっているのですか?

4

1 に答える 1

1

デリゲートを非同期で呼び出すことにより、作業をスレッド プールに移動します。あなたはまだ糸を燃やしています。何も得られず、パフォーマンスが低下します。

真の非同期IOをトリガーできる場合、非同期はほとんど意味があります。

于 2013-01-24T20:34:55.437 に答える