このトピックでは、Windows Communication Foundation (WCF) サービスをホストするためのベスト プラクティスについて説明します。
WCF サービスを DLL として実装する
WEB アプリケーションの \bin ディレクトリに展開される DLL として WCF サービスを実装すると、Web アプリケーション モデルの外部 (たとえば、インターネット インフォメーション サービス (IIS) が展開されていない可能性があるテスト環境でサービスを再利用できます。
IIS-Hosted アプリケーションのサービス ホスト
命令型のセルフホスト API を使用して、IIS ホスティング環境でネイティブにサポートされていないネットワーク トランスポートをリッスンする新しいサービス ホストを作成しないでください (たとえば、IIS 6.0 では TCP 通信がネイティブにサポートされていないため、TCP サービスをホストするために IIS 6.0)。 この方法は推奨されません。 命令型に作成されたサービス ホストは、IIS ホスティング環境内では認識されません。 重要なポイントは、ホスト アプリケーション プールがアイドル状態であるかどうかを判断するときに、命令型に作成されたサービスによって実行される処理が IIS によって考慮されないことです。 その結果、このような命令的に作成されたサービス ホストを持つアプリケーションには、IIS ホスト プロセスを積極的に破棄する IIS ホスティング環境が用意されています。
URI と IIS-Hosted エンドポイント
IIS でホストされるサービスのエンドポイントは、絶対アドレスではなく、相対 Uniform Resource Identifier (URI) を使用して構成する必要があります。 これにより、エンドポイント アドレスがホスティング アプリケーションに属する URI アドレスのセット内に含まれることが保証され、メッセージ ベースのアクティブ化が想定どおりに行われることが保証されます。
状態管理とプロセスリサイクル
IIS ホスティング環境は、メモリ内のローカル状態を維持しないサービス用に最適化されています。 IIS は、さまざまな外部イベントと内部イベントに応答してホスト プロセスをリサイクルし、メモリに排他的に格納されている揮発性の状態が失われます。 IIS でホストされているサービスは、プロセスの外部 (データベースなど) またはアプリケーションのリサイクル イベントが発生した場合に簡単に再作成できるメモリ内キャッシュに状態を格納する必要があります。
注
WCF がメッセージ層の信頼性とセキュリティに使用するプロトコルでは、揮発性のメモリ内状態が使用されます。 WCF の信頼できるセッションとセキュリティ セッションは、アプリケーションのリサイクルのために予期せず終了する可能性があります。 これらのプロトコルを使用する IIS でホストされるアプリケーションは、アプリケーション層の状態を関連付けるために WCF が提供するセッション キー以外の何かに依存するか (アプリケーション層コンストラクトやカスタム相関ヘッダーなど)、ホストされたアプリケーションの IIS プロセスリサイクルを無効にする必要があります。
Middle-Tier シナリオでのパフォーマンスの最適化
中間層シナリオ (受信メッセージに応答して他のサービスを呼び出すサービス) で最適なパフォーマンスを得るために、WCF サービス クライアントをリモート サービスに 1 回インスタンス化し、複数の受信要求で再利用します。 WCF サービス クライアントのインスタンス化は、既存のクライアント インスタンスでサービス呼び出しを行う場合に比べてコストのかかる操作です。中間層のシナリオでは、要求間でリモート クライアントをキャッシュすることで、パフォーマンスが個別に向上します。 WCF サービス クライアントはスレッド セーフであるため、複数のスレッド間でクライアントへのアクセスを同期する必要はありません。
中間層のシナリオでは、 svcutil /a
オプションによって生成された非同期 API を使用してパフォーマンスが向上します。
/a
オプションを指定すると、ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) はサービス操作ごとにBeginXXX/EndXXX
メソッドを生成します。これにより、バックグラウンド スレッドで実行時間の長いリモート サービスの呼び出しが実行される可能性があります。
複数のホームまたは複数の名前を持つシナリオでの WCF
IIS Web ファーム内に WCF サービスを展開できます。一連のコンピューターは共通の外部名 ( http://www.contoso.com
など) を共有しますが、異なるホスト名によって個別にアドレス指定されます (たとえば、 http://www.contoso.com
は、 http://machine1.internal.contoso.com
と http://machine2.internal.contoso.com
という名前の 2 つの異なるマシンにトラフィックを送信する場合があります)。 この展開シナリオは WCF で完全にサポートされていますが、サービスのメタデータ (Web サービス記述言語) に正しい (外部) ホスト名を表示するには、WCF サービスをホストする IIS Web サイトの特別な構成が必要です。
WCF が生成するサービス メタデータに正しいホスト名が表示されるようにするには、明示的なホスト名を使用するように WCF サービスをホストする IIS Web サイトの既定の ID を構成します。 たとえば、 www.contoso.com
ファーム内に存在するコンピューターでは、IIS サイト バインディング *:80:www.contoso.com for HTTP and *:443:www.contoso.com for HTTPSを使用する必要があります。
IIS Microsoft 管理コンソール (MMC) スナップインを使用して、IIS Web サイトのバインドを構成できます。
異なるユーザー コンテキストで実行されているアプリケーション プールによって、一時フォルダー内の他のアカウントのアセンブリが上書きされる
異なるユーザー コンテキストで実行されているアプリケーション プールが、一時 ASP.NET ファイル フォルダー内の他のアカウントのアセンブリを上書きできないようにするには、アプリケーションごとに異なる ID と一時フォルダーを使用します。 たとえば、2 つの仮想アプリケーション /Application1 と /Application2 がある場合は、2 つの異なる ID を持つ 2 つのアプリケーション プール A と B を作成できます。 アプリケーション プール A は 1 つのユーザー ID (user1) で実行できますが、アプリケーション プール B は別のユーザー ID (user2) で実行でき、B を使用するように A と /Application2 を使用するように /Application1 を構成できます。
Web.configでは、 <system.web/compilation/@tempFolder> を使用して一時フォルダーを構成できます。 /Application1 の場合は "c:\tempForUser1" に、application2 の場合は "c:\tempForUser2" にすることができます。 2 つの ID に対応する書き込みアクセス許可をこれらのフォルダーに付与します。
その後、user2 は /application2 のコード生成フォルダー (c:\tempForUser1 の下) を変更できません。
非同期処理の有効化
既定では、IIS 6.0 以前でホストされている WCF サービスに送信されたメッセージは、同期的に処理されます。 ASP.NET 独自のスレッド (ASP.NET ワーカー スレッド) で WCF を呼び出し、WCF は別のスレッドを使用して要求を処理します。 WCF は、処理が完了するまで、ASP.NET ワーカー スレッドを保持します。 これにより、要求の同期処理が行われます。 要求を非同期に処理すると、要求を処理するために必要なスレッドの数が減るため、スケーラビリティが向上します。WCF は要求の処理中に ASP.NET スレッドを保持しません。 IIS 6.0 を実行しているマシンでは、サーバーをサービス拒否 (DOS) 攻撃に開放する受信要求を調整する方法がないため、非同期動作 の 使用はお勧めしません。 IIS 7.0 以降では、同時要求スロットルが導入されました: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0]"MaxConcurrentRequestsPerCpu
。 この新しいスロットルでは、非同期処理を使用しても安全です。 IIS 7.0 では、既定では非同期ハンドラーとモジュールが登録されます。 これがオフになっている場合は、アプリケーションの Web.config ファイル内の要求の非同期処理を手動で有効にすることができます。 使用する設定は、 aspNetCompatibilityEnabled
の設定によって異なります。
false
に設定aspNetCompatibilityEnabled
場合は、次の構成スニペットに示すようにSystem.ServiceModel.Activation.ServiceHttpModule
を構成します。
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
</system.serviceModel>
<system.webServer>
<modules>
<remove name="ServiceModel"/>
<add name="ServiceModel"
preCondition="integratedMode,runtimeVersionv2.0"
type="System.ServiceModel.Activation.ServiceHttpModule, System.ServiceModel,Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</modules>
</system.webServer>
true
に設定aspNetCompatibilityEnabled
場合は、次の構成スニペットに示すようにSystem.ServiceModel.Activation.ServiceHttpHandlerFactory
を構成します。
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
<system.webServer>
<handlers>
<clear/>
<add name="TestAsyncHttpHandler"
path="*.svc"
verb="*"
type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
/>
</handlers>
</system.webServer>