0

Web アプリケーションの 1 つで、かなり奇妙な動作に気付きました。ローカルの開発者ワークステーションでデバッグすると、すべて正常に処理されます (Cassini Development Webserver を使用)。IIS 6.0 を使用してリモート Web サーバーに公開すると、処理は約 4 ~ 5 分間正常に実行され、その後突然終了します。

「突然死ぬ」が何を意味するかは後で説明します。まず、失敗したコードの抜粋を示したいと思います。

// loads data from SAP Webservice and serializes it into database    
LoadXMLDataFromSAP();

// loop each item of a certain structure and parse data
foreach (var xItem in xSapData)
{
    // method determining a status, about 30 LOC, fast execution
    GetStatusCodeForContract(xItem);

    ...

    // methods to parse data blocks, about 400 LOC, slow execution (database etc.)
    TimeconsumingParserMethod1(xItem);
    TimeconsumingParserMethod2(xItem);
}

このコードは、デバッグ時に問題なく実行されます。実行には約 13 分かかります (すべてのデータを SAP と同期するときにのみ発生するため、問題ありません)。IIS 6.0 で SAME SAP データソースに対して SAME コードを実行すると、4 ~ 5 分後に実行が停止します。

最初に、プログラムは呼び出し "TimesumptionParserMethod1()" で System.NullReferenceException をスローし、次のループで "GetStatusCodeForContract()" で System.NullReferenceException を取得します。両方の呼び出しで同じパラメーターを使用しているため、メンバー "xItem" が null であるため、NullReferenceException がスローされると思います。

サーバー構成:

8 Core Intel machine
4 GB of RAM
RequestTimeout = 900 (15 minutes)
Memory usage = unlimited

IIS 6 または同様の運用サーバー環境でのこのような動作について知っている人はいますか?

4

1 に答える 1

0

さて、私はついに問題を突き止めました。ローカル テストサーバーの EventLog に問題があったため、IIS 例外の一部に気付きませんでした。

問題の根本はタイムアウト設定ではなく、ASP.NET 2.0 の AppDomain リサイクル動作です。Web リクエスト中に多くのフォルダー構造を変更すると、AppDomain がリロードされ、不思議な NullReferenceExceptions が発生します。

次の記事が問題の追跡に役立ちました: http://weblogs.asp.net/owscott/archive/2006/02/21/ASP.NET-v2.0- 2D00 -AppDomain-recycles_2C00_-more-common-than-前.aspx

リンクの下のコード スニペットは、使用される回避策です (サブフォルダーのファイル監視を無効にするだけで、web.config への変更とアセンブリは、自動展開のために AppDomain を再読み込みします)。

System.Reflection.PropertyInfo p = typeof(System.Web.HttpRuntime).GetProperty("FileChangesMonitor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

object o = p.GetValue(null, null);

System.Reflection.FieldInfo f = o.GetType().GetField("_dirMonSubdirs", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.IgnoreCase);

object monitor = f.GetValue(o);

System.Reflection.MethodInfo m = monitor.GetType().GetMethod("StopMonitoring", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); m.Invoke(monitor, new object[] { });
于 2009-11-30T16:22:50.717 に答える