3

最近、新しい ASP.NET MVC 4 Web アプリケーション (C#/Visual Studio) を開発しました。ローカルでのテストとデバッグの後、本番環境にデプロイし、ヘルス モニタリング メールをどんどん受け取り始めました。これらには異なる例外メッセージがありました。

  • スタックが空です。
  • コレクションが変更されました。列挙操作が実行されない場合があります。
  • アイテムは既に追加されています。辞書のキー: 'ALL_HTTP' 追加されるキー: 'ALL_HTTP' (他のキーも言及されています)。
  • 値が期待される範囲内にありません。

たとえば、単純に解決または再現できない一連のエラー タイプ全体。「Stack Empty」は、1 日に数 100 回 (たとえば、ユーザーの 1 ~ 10%) で最も多く発生するエラーであり、他のエラーが関連しているように見えるため、このエラーに焦点を当てます。部分的なスタック トレースを次に示します。

Exception information:
Exception type: System.InvalidOperationException
Exception message: Stack empty.
...
Stack trace:    at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Stack`1.Pop()
at System.Web.WebPages.TemplateStack.Pop(HttpContextBase httpContext)

示されているように、スタック トレースはほとんど完全に MVC フレームワーク (System.Web) に配置されています。一部のスタック トレースで定期的に発生する独自のコード内の唯一の場所は、要求された URL のビュー (.cshtml ファイル) と @Html.RenderAction() 呼び出しです。ここまでで、これらの多くを RenderPartial() 呼び出しにリファクタリングしました。これにより、スタック トレースにビューがなくなりましたが、一部の RenderPartial もいくつかのビューを提供するようになりました。

このエラーを検索すると、同時実行/並列実行が原因であることが示されました。これは、最初はローカルでエラーを再現できなかったが、本番環境では発生したという事実と一致しています。負荷テストは行っていませんが、多くのアプリケーション/リクエストを同時に開始することで、ローカルの開発者システムでエラーを再現できました。ただし、私たちのコードでは、明示的な並列命令では何も行われません。

これは、MVC ビューがスレッドセーフではないことに関連しているようです。しかし、他の誰もこれに遭遇したとは想像しがたいです。1 日に数千人の訪問者があり、常時約 30 人以上のアクティブ ユーザーがいます。悲しいことに、Google ランキングの低下 (この問題に関連) により、この数は現在減少しています。

この問題の解決策/アプローチを知っている人はいますか?

4

2 に答える 2

3

私は ASP.NET MVC 4 アプリケーションを開発していますが、あなたが言及したエラーにも遭遇しました。それらは異なっていても、同じソースを持っているようです。その理由 (および多くのコード変更) を見つけるために数時間を費やした後、ゼロから分析を開始しました。

私はカスタムルートを使用しており、そのルートにはいくつかのことをチェックし、データベースにアクセスするハンドラーがあるため、データベースアクセスにコメントすることから始めました。いくつかのブラウザー タブを非常にすばやく開く ([IISExpress] > [Show All Application] ウィンドウを使用するか、リンクで Ctrl キーを押しながらクリックする)。確かに数回試してみたところ、DBへのアクセス中に何かが間違っていると結論付けました。

public class MyNewRouteHandler : IRouteHandler {

    IHttpHandler MvcHandler;

    public IHttpHandler GetHttpHandler(RequestContext requestContext) {
        MvcHandler = new MvcHandler(requestContext);

        // some checkings and
        // some database access code 
        // that was commented

        return MvcHandler;
    }
}

同僚は、このメソッド内に小さな Thread sleep を追加することを提案しました: GetHttpHandler。その行によりエラーが再び表示され、問題がDBに関連していないことが示唆されました...私がそれを行ったとき、MvcHandlerオブジェクトがクラスプロパティとして定義されており、それが同時実行の問題と思われるものの原因である可能性があることがわかりました(ほぼ連続した複数のアクセスを実行した場合にのみ、問題が示されました)。MvcHandlerオブジェクトをメソッド内のローカル オブジェクトに移動しました。

public class MyNewRouteHandler : IRouteHandler {

    public IHttpHandler GetHttpHandler(RequestContext requestContext) {
        IHttpHandler MvcHandler = new MvcHandler(requestContext);

        // some checkings and
        // some database access code 
        // that was commented

        return MvcHandler;
    }
}

そしてテスト後、エラーはなくなりました。DBにアクセスした(および他のチェックを行った)すべてのコードのコメントを外しましたが、それでもエラーは見つかりませんでした。ほぼ 3 日が経過しましたが、すべてが正常に機能しています。

于 2012-12-11T16:59:42.693 に答える
0

この方法でほとんどCustom Route Handlerのエラーは解決しましたが、まだいくつか残っており、新しいメッセージがあります。そのうちの 1 つは私のコード行を指していて、それらすべてに共通して、辞書が MVC フレームワークによって処理されているという事実がありました。Custom Route Handler

私はそう仮定し、すべてのメソッド プロパティは、public IHttpHandler GetHttpHandler(RequestContext requestContext)前に述べたものだけでなく、メソッド内に移動しました。そのうちの 1 つはRouteDataコレクションでした... 最後に、2 日後にエラーが表示されなくなったようです。

于 2012-12-19T09:07:29.587 に答える