C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2007/03/23 02:09
[ インスタンス コンテキスト モード ]
WCFでは、サービスのインスタンス化方式が3種類あります。

クライアント毎にサービスのインスタンスを生成
クライアントを識別しサービスのインスタンスを生成し、クライアントが一連の処理を終えるまで ( クライアントのサービス プロキシ オブジェクトがクローズするまで ) インスタンスを保持します。

要求毎にサービスのインスタンスを生成
サービスのメソッドが呼び出される度にサービスのインスタンスを生成します。一つのインスタンスは一度のメソッド呼び出しにしか使用されません。

シングルトン
サービスのインスタンスは常に一つだけ存在し、すべてのクライアントの要求に対して同一のインスタンスが使用されます。


従来のASP.NET Webサービスでは、「 要求毎にサービスのインスタンスを生成」する方式しかサポートしていませんでした。.NET Remoting では、3つ全ての方式をサポートしていました。

WCFでは、完全にこの3つの方式をサポートしています。Webサービスでもクライアント毎にサービスのインスタンスを生成したり ( .NET Remoting の CAO における、リースやスポンサーといった概念はないようです。 ) シングルトンにすることができます。

WCFでは、既定で「クライアント毎にサービスのインスタンスを生成」する方式が適用されます。


[ インスタンス コンテキスト モードの指定 ]
インスタンス コンテキスト モードを指定するには、サービスクラスの属性として ServiceBehaviorAttribute クラス (System.ServiceModel) を付加し、この属性の InstanceContextMode プロパティ を設定します。このプロパティの型は InstanceContextMode 列挙体 (System.ServiceModel) です。
InstanceContextMode 列挙体には以下の3つの列挙値が用意されています。これらは、この記事の最初に挙げた3つの方式と関連付けされています。 ( デフォルトは "PerSession" 。 )

InstanceContextMode.PerSession
クライアント毎にサービスのインスタンスを生成

InstanceContextMode.PerCall
要求毎にサービスのインスタンスを生成

InstanceContextMode.Single
シングルトン


[ セッションモード ]
インスタンス コンテキスト モードが "PerSession" に設定されている場合、 サービス コントラクトの ServiceContractAttribute 属性SessionMode プロパティ が "Required" または "Allowed" に設定されている必要があります。このプロパティの型は SessionMode 列挙体 (System.ServiceModel) です。 ( デフォルトは "Allowed" 。 )


[ スロットルの設定 ]
[ behaviors ] - [ serviceBehaviors ] - [ behavior ] セクション に属する [ serviceThrottling ] セクション の各属性 ( プログラムコードで扱うのなら ServiceThrottlingBehavior クラス (System.ServiceModel.Description) の各プロパティ ) でスロットルの設定を行うことができます。

maxConcurrentCalls

一つのサービス インスタンスに対して可能な同時呼び出しの最大値です。
この値を超える要求は、待機状態 ( 順番待ち ) となります。
デフォルトは16です。

maxConcurrentInstances
同時に存在できるサービス インスタンスの最大値です。
この値を超える要求は、待機状態 ( 順番待ち ) となります。
デフォルトは Int32.MaxValue です。

maxConcurrentSessions
一つのサービスに対して可能な同時呼び出しの最大値です。
この値を超える要求は、待機状態 ( 順番待ち ) となります。
デフォルトは10です。


[ リリース インスタンス モード ]
インスタンス コンテキスト モードが "PerSession" 、あるいは "Single" に設定されている場合、特定のオペレーション コントラクトが呼び出された際に、サービス インスタンスを強制的に解放するよう設定することができます。
この設定を行うには、サービス クラスのオペレーション コントラクトの属性として OperationBehaviorAttribute クラス (System.ServiceModel) を付加し、この属性の ReleaseInstanceMode プロパティ を設定します。このプロパティの型は ReleaseInstanceMode 列挙体 (System.ServiceModel) です。この列挙体には以下の4つの値があります。 ( デフォルトは "None" 。 )

BeforeCall
オペレーション コントラクトが呼び出される前に、強制的にサービス インスタンスを解放します。

AfterCall
オペレーション コントラクトが呼び出された後に、強制的にサービス インスタンスを解放します。

BeforeAndAfterCall
オペレーション コントラクトが呼び出される前と呼び出された後の両方で、強制的にサービス インスタンスを解放します。

None
サービス インスタンスの解放は行いません。


[ クライアントのサービス プロキシ オブジェクトからの解放要求 ]
インスタンス コンテキスト モードが "PerSession" に設定されている場合、クライアントのサービス プロキシ オブジェクトがクローズすると、サービス インスタンスも自動で解放されます。
ただし、サービス クラスの ServiceBehaviorAttribute 属性の AutomaticSessionShutdown プロパティ が "false" に設定されている場合は、解放は行われません。 ( デフォルトは "true" 。 )
「クライアントのサービス プロキシ オブジェクトがクローズする」というのは、サービス プロキシ クラスが実装する ICommunicationObject インターフェイス (System.ServiceModel)Close メソッド のことです。
( もう少し細かいことを言えば、クライアントのサービス プロキシ クラスが WSDL ファイルから自動生成されたクラスなら ClientBase ジェネリック クラス (System.ServiceModel)Close メソッド 、クライアントのサービス プロキシ クラスが ChannelFactory ジェネリック クラス (System.ServiceModel)CreateChannel メソッド から動的に生成されたクラスなら、そのクラスが実装した ICommunicationObject インターフェイス (System.ServiceModel)Close メソッド ってトコです。 )


[ 解放について ]
リリース インスタンス モードを設定したオペレーション コントラクトによって解放されたサービス インスタンスや、クライアントのサービス プロキシ オブジェクトがクローズしたため解放されたサービス インスタンスが、IDisposable インターフェイスを実装している場合、即座に IDisposable.Dispose メソッドが呼び出されます。 ( IDisposable インターフェイスを実装していない場合は当然Disposeメソッドの呼び出しは行われません。 )
その後、サービス インスタンスは GC 待ちとなります。
もう眠いから、サンプルプログラムは後日公開予定

あくまでも予定だからね!
タグ: .NET C# WCF


突然のコメント失礼します。
WCF関連の情報が少ない中、いつも参考にさせて頂いています。
WCFのサイトを作成されるとのことなので、大変楽しみにしています。
おそらく日本初?のWCFサイトになるかと思いますので期待大です。
自分も日々苦心しながらWCFと格闘しています。
その中で以下のような現象が発生したのでもしこれらに関して何かご存知
でしたら教えて頂けると有難いです。

wsHttpBindingでInstanceContextMode.PerSessionな設定で、
<reliableSession enabled="false">の場合ではインスタンスが呼び出し毎に作成され、
<reliableSession enabled="true">だとクライアント毎に作成されるという現象になっています。
netTcpBindingの場合はreliableSessionに関係なく、クライアント毎に作成されbasicHttpBinding
ではそもそもreliableSessionが設定できないため、呼び出し毎の作成しかできませんでした。
(サービスクラスのコンストラクタとメソッド中でカウンターを作成して確認)

また
basicHttpBindingでmessageEncoding="Mtom"の場合、500件程度のデータセットを返すようなある程度
大きなサイズのデータの送信では途中でエラーが発生しました。
(Mtomリーダーの作成に失敗しました。)
同様のデータでもwsHttpBindingでは発生しませんでした。
(やはりbasicHttpBindingでは正規な使用法ではないからでしょうか。)

2007.04.13 20:17 URL | ほにゃ #90LdKUd6 [ 編集 ]


ほにゃさん、はじめまして!
コメントありがとうございます^^

WCFのサイトはまだ準備段階でして ( しかもあまり捗ってない^^; ) 、気長に待って頂ければ幸いです m(_ _)m


InstanceContextMode.PerSessionについてですが、ReliableSession の設定によっては、インスタンスが呼び出しごとに生成されてしまうというのは見落としていました。貴重な情報を提供して頂き、ありがとうございます m(_ _)m
ちょっと調べてみましたが、バインディング セットによっては、セッションがサポートされていなかったり、セッションの有効・無効が ReliableSession に依存したりするようです。
例えば、WSHttpBindingはReliableSession が有効な場合のみセッションがサポートされます。BasicHttpBinding ではサポートされません。NetTcpBinding や NetNamedPipeBinding では、ReliableSession とは無関係に常にサポートされます。


次に、大容量データの通信で、WsHttpBinding では成功し、BasicHttpBinding では失敗するという件ですが、これはWsHttpBinding で WS-ReliableMessage によって高信頼な通信が行われるからかと思います。 ( あくまで予想ですが ^^; )
WS-ReliableMessage も、先ほどの ReliableSession 属性によって設定します。BasicHttpBinding は WS-ReliableMessage をサポートしていませんので、大容量データの通信でデータの破損が生じたのかもしれません。データの破損率はネットワークの帯域等によるかと思います。
以前、WS-ReliableMessage を適用せずにイントラネット上で 100MB 程のデータを通信するテストを行ったことがありますが、その時は一度もそのような現象が発生しませんでした。 ( まぁ、たまたまかもしれませんがw せいぜい10回くらいしか試してなかったし ^^; )

2007.04.14 01:43 URL | よこけん #Ay6tTHf6 [ 編集 ]


ほにゃです。
素早い返信ありがとうございます!

またわざわざ調べて頂いて恐縮です。おかげでインスタンスの件はもやもやがすっきりしました。
Mtomの件はそういえばBasicHttpBindingの送信で画像データが欠損するデモサイトがありましたね・・
相互運用などでやむ得ない場合以外は通常のアプリ用途ではNetTcpBindingまたはWsHttpBindingを利用した方がよさげですね。
サイトの件はご苦労されてるようで・・・ブログでも全然構いませんので情報をバシバシ載せてください!
ただ出始めの頃のASPみたいにユーザー主体の情報交換の場があればWCFの情報も集まるかもですね!
(MSDNのフォーラムとかあるようですが敷居が高いのか、繁盛していないようです・・)

2007.04.16 20:02 URL | ほにゃ #90LdKUd6 [ 編集 ]












トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/110-b6dc8ec5