0

サーバーの再起動直後に WMI または ADSI を使用して Windows サービス (C# で記述され、「自動」スタートアップに設定) からアプリケーション プールを開始すると、奇妙な状況に遭遇しました。

この問題について説明します。

次のメイン プロセスを含む大規模なアプリケーション (Windows 2003 Server SP2、IIS 6.0) を開発しています (これらのプロセスは、アプリケーションの起動時に Windows サービスの起動手順を使用して呼び出され、初期化されます)。

1) XServer1.exe、XServer2.exe - これらのプロセスはネイティブ COM-Exe サーバーであり、いくつかのロジックが含まれていますが、主に DCOM (主に .NET2COM interOp 呼び出しと純粋な COM 呼び出し) を介して他のプロセスに COM オブジェクトを提供します。たとえば、従来の ASP の「アプリケーション スコープの静的オブジェクト」(w3wp.exe) の一部は、これらのプロセス内に「存在する」COM オブジェクトです。

2) dllhost.exe - これは COM+ アプリケーションです。一部の DLL は、「状態サーバー」として機能するこのプロセスに読み込まれます (ASP.NET アウト プロセス セッション サーバーと同じ考え方ですが、従来の ASP ページ用です)。

3) 3 つの異なる IIS アプリケーション プール (appPool1\2\3 と呼びます) - ASP ページ、ASP.NET ページ、WCF サービスなどのコンテナー。これらのアプリケーション プール (w3wp) 内のコード (ネイティブ C++ COM dll および C#) .exe の) は通常、(1) & (2) で説明されているプロセスに対して DCOM 呼び出しを行います。Web ガーデンとして構成できるのは appPool1 のみです。

アプリケーションを開始/停止するために、これらの手順を制御する Windows サービス (C#) を作成しました。サービス プロセスは XWinService.exe と呼ばれます。このサービスは、次の Windows サービスに依存します (リストは最初の 4 つのサービスから始まり、継続的な試みにより、次のようなリストが作成されました...)。

W3SVC

aspnet_state

COMSysApp

DcomLaunch

winmgmt

lanmanserver

ランマンワークステーション

セクロゴン

ブラウザ

TermService

アプリケーションの停止手順の概要 (サービスによって実装されます):

1) 3 つの IIS アプリケーション プール (appPool1\2\3) をすべて停止します。これは、アプリケーションのシャットダウン時に w3wp.exe プロセスがジャンプするのを防ぐために行われます。これは、C# (system.Management.dll) の WMI で実装されます。

2) XServer1\2.exe を停止します。

3) COM+ アプリケーション (dllhost.exe) を停止します。

アプリケーションの開始手順の概要 (サービスによって実装):

1) 停止手順を実行します。これにより、時間になる前に HTTP ヒットが w3wp.exe プロセスを起動しないことが保証されます。

2) XServer1\2.exe COM-Exe サーバーの呼び出しと初期化 - w3wp.exe 呼び出しの前に初期化が必要です。オブジェクトが初期化された後でのみ、w3wp.exe はこれらのサーバーにアクセスできます。これは、.NET2COM InterOp (最終的には DCOM) によって実装されます。

3) dllhost.exe (COM+ アプリケーション) プロセスを呼び出して初期化 - これは ComAdmin Catalog API (C#) によって実装されます。

4) 3 つのアプリケーション プールを開始します。これにより、着信 HTTP ヒットが w3wp.exe プロセスを起動し、要求の処理を開始できるようになります。

これは、アプリケーション プール (WMI) の開始と停止を担当する C# コードです。このコードは、サービス プロセス (XWinService.exe) で実行されます。

    ConnectionOptions co = new ConnectionOptions(); 
ManagementScope scope = new ManagementScope(@"\\localhost\root\MicrosoftIISV2", co); 
foreach (string appPool in AppPools) 
{ 
   string objPath = string.Format("IISApplicationPool.Name='W3SVC/AppPools/{0}'", appPool); 
   using (ManagementObject mc = new ManagementObject(objPath)) 
  {
    mc.Scope = scope; 
    if (Operation.ToLower() == "start") 
    {
     mc.InvokeMethod("Start", null, null); // ### The problematic line of code ### 
    } 
    else if (Operation.ToLower() == "stop") 
   { 
      mc.InvokeMethod("Stop", null, null); 
   } 
   else if (Operation.ToLower() == "recycle") 
  {
     mc.InvokeMethod("Recycle", null, null); 
  }

 } 

}

 </p>

今問題:

サーバーを再起動する前に、サービスを手動で (services.msc ツールから) 開始すると、問題なく成功します。また、止めてもOKです。サービスを「自動」で開始するように設定しました。つまり、サーバー (Win2K3 SP2) が起動してサーバーを再起動したときに開始されます。サーバーが起動したとき (ログイン画面が表示されたとき)、サービスは「スタック」 (ステータス = 「開始中」) であり、決して開始されません (2 日間ハングします!)。

プロセスを分析すると、次のことが明らかになりました。

1) XWinService.exe プロセスが、問題のあるコード行 (### の上の ###) でスタックしていました。これは、プロセスを強制終了するまで 2 日間ハングしました。注意: アプリケーション プールのシャットダウン (Start 手順は Stop 手順で始まります) はハングしませんでした。

2) この「ハング」中に XWinService.exe から (DebugDiag ツールを使用して) 取得した DUMP ファイルから、待機中のスレッドを確認できます。これは、その (ネイティブ) スタック トレースです。

    Thread 6 - System ID 2784
Entry point mscorwks!Thread::intermediateThreadProc
Create time 11/19/2009 1:40:05 PM
Time spent in user mode 0 Days 00:00:00.078
Time spent in kernel mode 0 Days 00:00:00.781


This thread is making a COM call to multi-threaded apartment (MTA) in process 884
Function Source
ntdll!KiFastSystemCallRet  
ntdll!NtRequestWaitReplyPort+c  
rpcrt4!LRPC_CCALL::SendReceive+230  
rpcrt4!I_RpcSendReceive+24  
ole32!ThreadSendReceive+138  
ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+112  
ole32!CRpcChannelBuffer::SendReceive2+d3  
ole32!CAptRpcChnl::SendReceive+ab  
ole32!CCtxComChnl::SendReceive+1a9  
rpcrt4!NdrProxySendReceive+43  
rpcrt4!NdrClientCall2+206  
rpcrt4!ObjectStublessClient+8b  
rpcrt4!ObjectStubless+f  
….  

このスレッドは、プロセス 884 のコンポーネント (svchost.exe) を (DCOM 経由で) 呼び出しており、次のサービスを実行しています: AeLookupSvc、AudioSrv、Browser、CryptSvc、dmserver、EventSystem、helpsvc、lanmanserver、lanmanworkstation、Schedule、seclogon、SENS、ShellHWDetection 、TrkWks、winmgmt、wuauserv、WZCSVC。

ご覧のとおり、「winmgmt」サービス (WMI を担当) がこのプロセスで実行されており、私たちのサービスはそれに依存しているため、winmgmt が開始された後にサービスが開始されます (IIS W3SVC サービスも同様です)。

svchost.exe プロセス (884) がダンプされ、プロセス 2880 にアクセスするスレッド (DCOM 呼び出しが終了するのを待っている) を確認できます。これは - wmiprvse.exe (これは WMI サーバーだと思います。関連性があるかどうかはわかりません) 、しかし、このプロセスの 2 つのインスタンスがありました)。これは、スレッドのネイティブ コール スタックです (svchost.exe 内):

     Thread 48 - System ID 3816
Entry point wbemcore!CCoreQueue::_ThreadEntry
Create time 11/19/2009 1:40:56 PM
Time spent in user mode 0 Days 00:00:00.00
Time spent in kernel mode 0 Days 00:00:00.00


This thread is making a COM call to multi-threaded apartment (MTA) in process 2880

Function Source
ntdll!KiFastSystemCallRet 
ntdll!NtRequestWaitReplyPort+c 
rpcrt4!LRPC_CCALL::SendReceive+230 
rpcrt4!I_RpcSendReceive+24 
ole32!ThreadSendReceive+138 
ole32!CRpcChannelBuffer::SwitchAptAndDispatchCall+112 
ole32!CRpcChannelBuffer::SendReceive2+d3 
ole32!CAptRpcChnl::SendReceive+ab 
ole32!CCtxComChnl::SendReceive+1a9 
… 

3)サービスを「手動」に設定して開始する(手動-サーバーにログインした後、または再起動直後に別のサーバーからリモートで開始した後)は問題ありません-何もハングしません。

4) サービスを (レジストリから!) 削除し、Windows の「スタートアップ」フォルダにバッチ ファイルを配置しました。このバッチ ファイルはサービスのコードを呼び出しますが、通常の C# 実行可能ファイルとして実行します。サーバーの再起動後も、同じ問題のあるコード行でハングします (これも... 強制終了するまで 2 日間)。

5) WMI の代わりに ADSI (System.DirectoryServices) を使用しても、同じ結果が得られました (アプリケーション プールの起動が停止しました!)。

私たちは過去 2 週間、これを掘り下げてきました...

私の質問:

==========

1) 誰かが同じ問題に遭遇しましたか?

2) ハングする理由を知っている人はいますか? 留意すべき追加のサービス依存関係はありますか?

3) この問題の解決策はありますか?

4) サービスが「自動」スタートアップに設定されている場合にのみ、再起動後にこれが発生するのはなぜですか? 手動で行うと、すべて問題ありません。

***** 小さな更新:**

VM (VMware ステーション) では、サービスが再起動後、起動するまで平均 40 分ほどハングすることがわかりました (注: 起動に失敗することはありませんが、40 分は長すぎます)。システム イベント ログに、サービスが 16 分以上ハングしたことを示すイベント ログ メッセージが記録されます (ソース: Service Control Manager、イベント ID: 7044)。

「通常の」マシン (本物の金属) では、サービス開始までの平均時間は ~55 時間です!!! ここでも、前述のようにイベント ログ エントリが記録されます。

平均値は、10 の異なる VM と 8 つの異なる「実」サーバーから計算されました。

4

1 に答える 1

0

誰も返信していないようですが、とにかくいくつかのニュースを投稿します...

アプリケーション プールを開始する前に、サービス ステータスを「開始」に設定し、new Thread(...)上記のコードを実行する新しいスレッド ( ) を開く (WMI でアプリケーション プールを開始する) と、問題が解決することがわかりました。

OnStartこれは、サービスのメソッドの擬似コードです。

OnStart {
     StopProcedure();

     InvokeInitXServer1And2(); //COM-Exe servers

     InvokeInitCOMPlusApplication(); //dllhost.exe

     SetServiceStatus(SERVICE_STARTED);

     Thread worker = new Thread(new threadStart(IISAppPoolStartWMI); //Calls the code
}

これは、サービスが妥当な時間内に開始される唯一の方法です (最大 3 分、実マシンと VM の両方の平均で 1.5 分!)、w3wp.exe プロセスが開始されます。

誰かがそれについての説明 (MTA\STA の問題?!?!?) を持っているなら、私は喜んでそれを読みます。

于 2009-11-23T01:33:17.423 に答える