wsHttpを使用して WCF を使用して( NetDataContractSerializer経由で) 大量のシリアル化されたオブジェクト グラフを転送する必要がある場合があります。メッセージ セキュリティを使用しており、引き続き使用したいと考えています。このセットアップを使用して、シリアライズされたオブジェクト グラフを転送したいと思います。転送しようとすると、System.InsufficientMemoryException 型の例外が表示されるようになりました。
少し調査した結果、WCF では、デフォルトで、サービス呼び出しの結果が、シリアル化されたデータを含む単一のメッセージ内に含まれており、このデータは、メッセージ全体が完全に書き込まれるまでデフォルトでサーバーにバッファリングされるようです。したがって、メモリ例外は、サーバーがバッファがいっぱいであるために割り当てることができるメモリ リソースを使い果たしているという事実によって引き起こされています。私が遭遇した 2 つの主な推奨事項は、ストリーミングまたはチャンクを使用してこの問題を解決することですが、それが何を伴うのか、また現在のセットアップ (wsHttp/NetDataContractSerializer/Message Security) でどちらの解決策も可能かどうかは明確ではありません。これまでのところ、メッセージの暗号化と復号化は部分的なメッセージではなく、データのセット全体に対して機能する必要があるため、ストリーミング メッセージ セキュリティを使用しても機能しないことを理解しています。チャンクは可能かもしれませんが、私がリストした他の制約でどのように行われるかは明確ではありません。利用可能なソリューションとその実装方法について誰かがガイダンスを提供できれば、非常に感謝しています。
私の場合、通信の両側を所有および制御し、どちらの側にも転送されるデータに共有インターフェイス パターンを使用するため、他のクライアントとの相互運用性については特に心配していません。したがって、私は、wsHttp をメッセージ セキュリティと共に使用して、NetDataContractSerializer を使用してシリアル化されたオブジェクト グラフを転送するという制約の範囲内に収まるアイデアを受け入れており、既存のサービスと周囲のインフラストラクチャを大幅に変更する必要がないソリューションを好みます。
関連リソース:
- チャンキングチャンネル
- 方法: ストリーミングを有効にする
- WCF 経由の大きな添付ファイル
- カスタム メッセージ エンコーダー
- InsufficientMemoryException の別の発見
- 非二重チャンキング チャネルが必要
- WCF と遅延実行による大きなコンテンツのストリーミング
このデータに対して実行できるあらゆるタイプの圧縮にも興味がありますが、クライアントが gzip を自動的にサポートするように、.NET 4.0 に移行できるようになったら、トランスポート レベルでこれを行うのがおそらく最善のようです。これを正しく理解していればヘッダー。
更新 (2010-06-29):
バッファリングされたメッセージが大きすぎることが問題の原因であるという結論に達した方法に関するいくつかの歴史。もともと、テスト中に以下のCommunicationExceptionを見ました。
基になる接続が閉じられました: 接続が予期せず閉じられました。
最終的に、これを実行してさらにログを記録した後、指定されたメッセージで問題を引き起こしている基になるInsufficientMemoryException例外を見つけました。
268435456 バイトのマネージ メモリ バッファの割り当てに失敗しました。使用可能なメモリ量が少ない可能性があります。
これは、次の方法に由来します。
System.ServiceModel.Diagnostics.Utility.AllocateByteArray(Int32 サイズ)
つまり、失敗は配列の割り当てに起因します。シリアル化された同じデータをディスクに書き込むと、約 146MB を占めます。それを半分に減らすと、エラーが発生しなくなりますが、バッファを壊す特定のしきい値と、それがシステムに固有なのか、それともいいえ。
更新 (2010 年 12 月 6 日):
この時点で、次の説明を求めていると思います。私の理解では、デフォルトではメッセージセキュリティを備えたWCF wsHttpでは、応答がクライアントに送り返される前にメッセージ全体(通常は返されるデータセット全体)をサーバーにバッファリングする必要があり、問題が発生します。
可能な解決策:
- データ サイズの制約 - 送信バッファの最大容量を消費しないようにするために、なんらかの形式の圧縮、エンコード、またはメソッドのようなページングを使用して返される実際のデータの制限を使用します。
- ストリーミング - WCF を介してストリーミング方式で大量のデータを送信できますが、これらの手法ではすべてのデータをバッファリングする必要があるため、これは wsHttp または MessageSecurity と互換性がありません。
- Chunking Channel - データを個別のメッセージに分割できるようにしますが、現時点では、これがサービス コントラクトの設計に及ぼす制約と、メッセージ バインディングで wsHttp を引き続き使用できるかどうかはわかりません。
返すことができるデータを制限することは、ある程度までしか機能せず、ストリーミング オプションと同様に、これらのオプションでは、WCF サービス呼び出しの外部で多くの下位レベルの作業をコーディングする必要があります。したがって、私が知る必要があるのは、単一のデータ セットをサーバー上で個別のメッセージに分割し、クライアント上でつなぎ合わせることができるようにすることで、大きなメッセージの問題を回避できる可能性のあるチャンキング チャネルの実装があるかどうかということです。これにより、既存のサービス コントラクトのインターフェイス/形状を変更する必要がなくなり、メッセージ セキュリティと wsHttp を使用しながら、各サービス実装のクライアントとサーバーの部分からプロセスがほとんど隠されます。チャンキング チャネルで、ストリームを公開するためにサービス コントラクトを書き直す必要がある場合は、必要ありません。これがストリーミング ソリューションと実際にどのように異なっているかがわかります。誰かが私のためにこれらの質問に簡単に答えることができれば、賞金を授与し、それを答えとしてマークします.