上記のエラーは、プロセスベースのWCFパフォーマンスカウンターを使用している場合にも、アプリケーションログで発生する可能性があります。この症状は、アプリケーションイベントログの3つのエラーのブロックです。
パフォーマンスカウンターがロードされませんでした。
カテゴリ名:ServiceModelService 3.0.0.0
カウンター名:呼び出し
Exception:System.InvalidOperationException:インスタンス'abc@def|service.svc'は、プロセスの存続期間中にすでに存在します。削除されるか、それを使用しているプロセスが終了するまで、再作成または再利用することはできません。
これは常に、システムイベントログの次の情報メッセージの直後に発生します。
プロセスIDが「nnnn」でアプリケーションプール「MyAppPool」にサービスを提供しているワーカープロセスが、許可された処理時間制限に達したため、リサイクルを要求しました。
これにより、このサービスのパフォーマンスモニターカウンターが、明らかに数時間使用できなくなります。
ServiceModelService 3.0.0.0
バージョン番号は、使用している.NETのバージョンによって異なります(これは.NET 3.5を使用してテストされています)。
バックグラウンド
障害は、ワーカープロセスが処理時間制限に達することによってトリガーされ、その時点でリサイクルする必要があります。これは、IISアプリケーションプールのリサイクル設定(IIS 6.0以降、つまりWindows Server 2003以降)で設定されます。ワーカープロセスをリサイクルすると、新しいプロセスベースのパフォーマンスカウンター名が古いものと競合し、エラーが発生します。これは、IISが重複リサイクルを使用しているためです。この場合、終了するワーカープロセスは、新しいワーカープロセスが開始されるまで実行され続けます。
再生
(Windows Server 2003 = IIS 6.0でテスト済み)
- WCFサービスを作成します。
- セクションのに以下を追加します。
web.config
<system.serviceModel>
<diagnostics performanceCounters="All" />
- [プロパティ]→[リサイクル]のサービスの[アプリケーションプール]プロパティで、リサイクルワーカープロセスを1分に設定します。アプリケーションプールを手動でリサイクルしても効果はありません。これは、ワーカープロセスからリサイクルの要求が作成されないためです(イベントビューアのシステムログに
W3SVC
情報イベントが含まれていることがわかります)。
- soapUIで、WCF操作のテストスイート/テストケース/テストステップ/テストリクエストを作成します。
- テストケースをsoapUIの負荷テストに追加するか、loadUIを使用して、1秒あたり1回の速度で呼び出しを開始します。
- 1分ごとに、ワーカープロセスはリサイクルを要求します(システムログに表示されます)。2分ごとに、からのアプリケーションログに3つのエラーのバッチが発生し
System.ServiceModel 3.0.0.0
ます。
- そのサービスのパフォーマンスカウンターは、ワーカープロセスが再度リサイクルされるまで使用できなくなります。(注:この時点でリサイクル期間をより高い値に設定して、パフォーマンスカウンターが使用できない期間を確認すると、実際にプロセスがリサイクルされ、カウンターが再び使用可能になります。)
可能な解決策
解決策1-赤いニシン
ホットフィックスKB981574は、ホットフィックスKB971601に取って代わります。後者の修正プログラムは問題を説明しています。
修正:アプリケーションを監視するパフォーマンスカウンターは、アプリケーションが終了して再起動すると応答を停止し、.NETFramework2.0を実行しているコンピューターでSystem.InvalidOperationException例外を受け取ります。
以前の修正プログラムを適用しても、問題は解決しません。後者の修正プログラムを適用すると、アプリプールエラーが発生しました。
ソリューション2-実用的なソリューション
カスタムサービスホストを公開するサービスホストファクトリを作成することができます。
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace MyNamespace
{
public class WebFarmServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
return new WebFarmServiceHost(serviceType, baseAddresses);
}
}
public class WebFarmServiceHost : ServiceHost
{
public WebFarmServiceHost(
Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
protected override void ApplyConfiguration()
{
base.ApplyConfiguration();
Description.Name = "W3wp" + Process.GetCurrentProcess().Id +
Description.Name;
}
}
}
そして、サービスマークアップ.svc
ファイルでファクトリを参照してください。
<%@ ServiceHost Language="C#" Debug="true" Factory="MyNamespace.WebFarmServiceHostFactory" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" %>
最終的な調整
残念ながら、これにより問題の発生頻度は大幅に低下しますが、それでも発生します(これについて正確な統計を測定していませんが、概算で約30分の1になります)。
問題を完全に解決するように見える簡単な調整は、直前にスリープコマンドを追加することbase.ApplyConfiguration();
です。
Thread.Sleep(1);
これは、ワーカープロセスのリサイクルごとに1回だけ発生するため、サービスのパフォーマンスへの影響はごくわずかです。この値を上げる必要があるかもしれません(構成可能にすることができます)が、最小設定の1msでうまくいきました(このコマンドが実際にどれだけ長くスリープするかについての議論)。
解決策3-最も簡単な修正
IISには、DisallowOverlappingRotation
メタベースプロパティがあります。これは次のように設定できます(MyAppPool
アプリケーションプールの例)。
cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET w3svc/AppPools/MyAppPool/DisallowOverlappingRotation TRUE
ソリューションの比較
解決策3では、IISの重複したリサイクルがないために、ワーカープロセスがリサイクルされると、サイトがより長くダウンします。
5スレッドで毎秒100以上のトランザクションを使用する基本的なWebサービスのsoapUI負荷テストでは、ワーカープロセスがリサイクルされるたびに、新しいトランザクションがブロックされる「フリーズ」が数秒間明らかになりました。より複雑なWebサービスをテストすると、このフリーズはさらに長くなりました(8秒以上)。
ソリューション#2は、そのようなブロッキングを生成せず、リサイクル中の応答の流れがスムーズで、perfmon競合エラーを生成しませんでした。
結論
低遅延が要件ではないWebサービスの場合、ソリューション#3を使用できます。負荷分散と1日の静かな時刻がわかっている場合は、リサイクルを設定した時刻に毎日行うように設定することもできます(これは、IISの同じタブで実行できます)。Webファームが使用された場合、これはずらされる可能性さえあります。
このような遅延を許容できないWebサービスの場合、ソリューション#2が最善の方法であると思われます。