2012-02-23 16 views
3

私のASP.NET MVC3アプリケーションは、Ninjectを使用してラッパーを介してサービスインスタンスをインスタンス化します。コントローラのコンストラクタにはIMyServiceパラメータがあり、アクションメソッドはmyService.SomeRoutine()を呼び出します。サービス(WCF)は、wsHttpBindingを使用してSSL経由でアクセスされます。メモリリーク - WCF例外

私はWCF(オブジェクトグラフ内で直列化または非直列化できる項目の最大数)で設定した最大値を超える非常に多くの結果を返す検索ルーチンを用意しています。このような状況が発生すると、サービスとクライアントの両方のアプリケーションプールが著しく増加し、依頼の最後を過ぎても十分に膨らんでいます。

結果の数を制限したり、送信されるデータの量を減らすためにDTOを使用することができます。つまり、私はメモリリークのように見えるものを修正したいと思います。

CLR Profiler

を使用し、私は、ヒープの大部分は、以下で使用されていることがわかり:

  • System.RunTime.IOThreadTimer.TimerManager
  • System.RunTime.IOThreadTimer.TimerGroup
  • System.RunTime .IOThreadTimer.TimerQueue
  • System.ServiceModel.Security.SecuritySessionServerSettings
  • System.ServiceModel.Channels.SecurityChannelListener
  • System.ServiceModel.Channels.HttpsChannelListener
  • System.ServiceModel.Channels.TextMessageEncoderFactory
  • System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder
  • System.Runtime.SynchronizedPool
  • System.Runtime.SynchronizedPool.Entry []
  • ... TextMessageEncoderFactory.TextMessageEncoder.TextBufferedMessageWriter
  • System.Runtime.SynchronizedPool.GlobalPool
  • System.ServiceModel.Channels.BufferManagerOutputStream
  • System.Byte [] []
  • System.Byte [](92%)

また、Iは、空のリストを返すために、検索ルーチンを変更する場合(ただし、NHibernateの情報はバックグラウンドでログに記録されますが、ロギングによって確認されます)、アプリケーションプールのサイズは変更されません。検索ルーチンが例外なく重要な結果を返す場合、アプリケーションプールサイズは変更されません。私は、オブジェクトのリストがシリアル化され、例外が発生したときにリークが発生すると考えています。

私は最新のNinjectにアップグレードし、log4netを使用して、サービスクライアントがその状態に応じてクローズまたはアボートされたことを確認しました。私が面白いと思ったのは、サービスラッパーがファイナライズされ、明示的に処理されていないということだけでした。

このシナリオでは、アプリケーションプールがメモリを解放していない理由を調べるのに問題があります。他に何を見ているべきですか?

更新日:ここにはバインディングがあります...

<wsHttpBinding> 
<binding name="wsMyBinding" closeTimeout="00:01:00" openTimeout="00:01:00" 
    receiveTimeout="00:02:00" sendTimeout="00:02:00" bypassProxyOnLocal="false" 
    transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
    maxBufferPoolSize="999999" maxReceivedMessageSize="99999999" 
    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="false" 
    allowCookies="false"> 
    <readerQuotas maxDepth="90" maxStringContentLength="99999" 
    maxArrayLength="99999999" maxBytesPerRead="99999" 
    maxNameTableCharCount="16384" /> 
    <reliableSession enabled="false" /> 
    <security mode="TransportWithMessageCredential"> 
    <message clientCredentialType="UserName" /> 
    </security> 
</binding> 
</wsHttpBinding> 

UPDATE#2:ここではNinjectは結合が、より多くの好奇心は、エラーメッセージです。私のラッパーは、MaxItemsInObjectGraphを正しく設定していないので、デフォルトを使用していました。私がこれを設定すると、漏れがなくなった。サービスがシリアル化されたデータをクライアントに送信し、クライアントがMaxItemsInObjectGraphを超えてクライアントを拒否すると、クライアントとサービスはシリアル化/非直列化データをメモリ内に保持していると考えられます。

Ninjectバインディング:

Bind<IMyService>().ToMethod(x => 
    new ServiceWrapper<IMyService>("MyServiceEndpoint") 
    .Channel).InRequestScope(); 

エラーメッセージ:

のInnerExceptionメッセージは' オブジェクトグラフにシリアライズまたはデシリアライズすることができるアイテムの最大数である' ました65536 '

これは実際にメモリリークを修正するものではありませんので、誰かがアイデアを持っている場合、何が原因で発生しているのか不思議です。

+0

ラッパーにはどのバインディングを使用しますか? –

+0

@Remo:上記のバインディングを追加しました - ありがとう! – Mayo

+0

申し訳ありませんが私は十分に明確ではなかった。私は、ラッパーの作成に使用されたNinject Bindingを意味しました。特にスコープは興味深い。 –

答えて

1

プロキシクライアントの作成と処分はどのように処理していますか?

WCF関連のメモリリークの最も一般的な原因は、WCFプロキシクライアントの誤操作であることがわかりました。

私はちょっとこのようusingブロックを使用してクライアントを包む最低でもお勧め:

using (var client = new WhateverProxyClient()) 
{ 
    // your code goes here 
} 

これは、メモリを解放し、クライアントが適切に閉じられ、処分されることを保証します。

この方法は少し議論の余地がありますが、クライアントの作成からメモリが漏れてしまう可能性はありません。

このトピックについては、hereをご覧ください。

+0

フィードバックをいただきありがとうございます。サービスラッパーには、クライアントがnullに設定される前に(その記事に類似したコードを使用して)クライアントがクローズ/アボートされることを確実にする廃棄とファイナライズがあります。私は、このシナリオのバリエーションを試して漏れを分離するためのテストハーネスを作成すると思います。あまりにも多くの変数があります。 – Mayo

+5

-1:あなたはその記事について知っているので、なぜ誰もが 'using'ブロックを使うことを提案していますか? –

関連する問題