2012-02-23 87 views
3

我的ASP.NET MVC3應用程序使用Ninject通過包裝實例化服務實例。控制器的構造函數具有IMyService參數,操作方法調用myService.SomeRoutine()。服務(WCF)通過SSL通過wsHttpBinding進行訪問。內存泄漏 - 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%)

此外,如果我修改搜索例程返回一個空列表(而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> 

更新#2:這裏是Ninject結合,但更好奇的是錯誤消息。我的包裝沒有正確設置MaxItemsInObjectGraph,所以它使用了默認值。一旦我確定了,泄漏就消失了。當服務將序列化數據發送到客戶端時,客戶端和服務似乎將序列化/反序列化的數據保存在內存中,並且客戶端因其超過MaxItemsInObjectGraph而拒絕該數據。

Ninject綁定:

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

錯誤消息:

設置InnerException消息是 '項目的最大數目,可以是 串行化或在對象圖反序列化是' '

這實際上並沒有解決內存泄漏問題,所以我仍然好奇如果任何人有任何想法會導致內存泄漏。

+0

你用什麼捆綁包裝? – 2012-02-23 23:21:07

+0

@Remo:我添加了上面的綁定 - 謝謝! – Mayo 2012-02-24 14:00:09

+0

對不起,我不夠清楚。我的意思是用於創建包裝的Ninject綁定。特別是範圍是有趣的。 – 2012-02-24 15:01:10

回答

1

你是如何處理你的代理客戶端創建和處置的?

我發現WCF相關內存泄漏的最常見原因是錯誤處理WCF代理客戶端。

我建議至少是有using塊包裹你的客戶還挺像這樣:

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

這可以確保客戶端正常關閉和處置,釋放內存。

雖然這種方法有點爭議,但它應該消除客戶端創建內存泄漏的可能性。

查看here瞭解更多關於此主題的信息。

+0

感謝您的反饋,使用此綁定時,應將包裝器置於MVC請求的末尾。服務包裝器有一個dispose和finalize,它們確保客戶端在被設置爲null之前關閉/中止(使用類似於該文章的代碼)。我想我會創建一個測試工具來試驗這個場景的變體來嘗試隔離泄漏。太多的變數現在。 – Mayo 2012-02-23 20:57:15

+5

-1:既然你知道那篇文章,爲什麼你會建議任何人使用'using'塊? – 2012-02-24 00:30:07