2014-10-29 42 views
0

下午好。內存泄漏 - Ninject,WCF,WEBApi,ChannelFactory

我正面臨着內存泄漏的問題,我想我知道發生這種情況的地方,但不知道我需要做什麼來修復它!希望你們能再次拯救我。

我真的已經嘗試谷歌它(很多),但我發現或測試結果沒有實際工作。

我使用了很多功能,但我不得不遵循客戶IT部門的一些架構規則,因此不能考慮這個主題,就像不使用Ninject或不使用WCF一樣例。我可以做什麼(也許我需要)是改變他們的實施方式。

這就是說,讓我們去看炸彈。

在我的項目中,表示層託管在一個服務器中,WCF服務及其所有依賴項(域,存儲庫等)位於另一個服務器中。

問題出在WCF服務器上,該服務器增加了從演示文稿到服務的每個請求的內存使用量,並且不會釋放此內存,直到服務器內存達到極限,並且服務器需要重新啓動,或者IIS應用程序池將被重新啓動。

下面所使用的技術:

領域模型,WCF,MVC4使用Web API,Ninject 3.2 MVC和WCF,AutoMapper映射從域DTO和扭轉,資源庫和NHibernate。

我已經檢查了Repository和NHibernate圖層,它們正確地處理它們的對象。

我使用Ninject注入WCF中表現爲按照App_Start:

public class NinjectConfiguration 
{ 
    public void Configure(IKernel container) 
    { 
     AddBindings(container); 

     var resolver = new NinjectDependencyResolver(container); 
     GlobalConfiguration.Configuration.DependencyResolver = resolver; 
    } 

    private void AddBindings(IKernel container) 
    { 
     container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()); 
     // ... 
    } 

    public TService CreateChannel<TService>() where TService : class 
    { 
     var factory = new ChannelFactory<TService>(string.Empty); 

     factory.Open(); 
     return factory.CreateChannel(); 
    } 
} 

呈現的Web.Config端點配置:

<system.serviceModel> 
    <client> 
     <endpoint address="http://MyEndPoint/PersonService.svc" binding="wsHttpBinding" bindingConfiguration="BindClientConfig" contract="MyContract.IPersonService" /> 
    </client> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="BindClientConfig" maxReceivedMessageSize="2147483647" sendTimeout="00:01:00"></binding> 
     </wsHttpBinding> 
    </bindings> 
    </system.serviceModel> 

我的WebAPI配置:

public class PersonController : ApiController 
{ 
    IPesrsonService _personService; 
    public PersonController(IPesrsonService personParam) { ... } 

    //Gets, Post, Put, Delete here and functional 

    protected override void Dispose(bool disposing) 
    { 
     if (_personService != null) 
     { 
      _personService.Dispose(); //This point is reached 
     } 
     base.Dispose(disposing); 
    } 
} 

而我的WCF處置(合同實現IDisposable):

public class PersonService : IPersonService 
{ 
    private IPersonDomain _personDomain; 
    public PersonService(IPersonDomain personDomainParam) { ... } 

    //... 
    protected virtual void Dispose(bool disposing) { ... } 

    public void Dispose() 
    { 
     Dispose(true); //This point is NEVER reached 
     GC.SuppressFinalize(this); 
    } 
} 

理論上,來自WebAPI的_personService.Dispose必須從WCF調用Dispose,但此Dispose WCF永遠不會到達。我可以從WCF獲得其他任何方法,但Dispose,我不能。

我的猜測是我錯過了Ninject配置中的一些東西,它創建了這個非託管孔。

看起來,表示層並沒有真正關閉到WCF的連接,這樣,終端在通信的另一端(WCF服務器)永遠打開並保留分配的內存。

我已經試圖改變NinjectConfiguration如下,但沒有成功:

private void AddBindings(IKernel container) 
{ 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).InScope(ctx => HttpContext.Current); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).OnDeactivation(CloseServiceConnection); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).OnDeactivation(CloseServiceConnection<IPersonService>); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).InScope(ctx => HttpContext.Current).OnDeactivation(CloseServiceConnection); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).InScope(ctx => HttpContext.Current).OnDeactivation(CloseServiceConnection<IPersonService>); 
    container.Bind<IPersonService>().ToMethod(ctx => CreateChannel<IPersonService>()).InScope(ctx => OperationContext.Current).OnDeactivation(CloseServiceConnection<IPersonService>); 
} 

public static void CloseServiceConnection<T>(T service) 
{ 
    (service as IDisposable).Dispose(); 
} 

也許CreateChannel從NinjectConfiguration類可以用另一種方式來創建這樣我就可以調用channel.Close(),但我不知道該怎麼做。

但是,這一切只是一個猜測。你發佈的一切,我會嘗試。

我感謝任何幫助,並非常感謝你的時間。

埃萊克圭多林

+1

我會建議爲每個服務調用創建一個新工廠可能是問題的一部分。 – sga101 2014-10-29 17:12:27

+0

真正的混亂是因爲我不知道如何在這種情況下調用WCF配置。我不知道它是Ninject的配置,還是我創建工廠的方式,我不知道如何從工廠調用Close(),這可以調用此函數。 在演示服務器中,內存很好,並處理它們的對象。 – 2014-10-29 17:29:55

+1

我沒有得到正確的結果:'PersonController'你想通過WCF *調用'IPersonService.Dispose()'*?或者換句話說:一個進程(其中'PersonController'住在哪裏)正在處理另一個進程的對象(其中'IPersonService'住在哪裏)? – BatteryBackupUnit 2014-10-30 07:16:15

回答

1

我會建議爲每個服務調用創建一個新的通道工廠可能是問題的一部分。創建一次,緩存它,然後根據需要重新使用它創建新頻道。如果您出於某種原因需要每次都創建一個新的,請記住隨後處理它。

+0

感謝您的快速回復。真正的混亂是因爲我不知道如何在這種情況下調用WCF配置。 – 2014-10-29 17:22:25

+0

很老了,但是這是否幫助? HTTP://計算器。com/questions/5145775/ninject-doesnt-call-dispose-on-objects-when-out-of-scope – sga101 2014-10-29 17:45:03

+0

我會盡力而爲,我會讓你知道 – 2014-10-29 20:49:39

0

我有同樣的問題,除非你的WCF契約從IDisposable繼承,那麼Dispose()永遠不會被調用。

每次創建一個新的ChannelFactory都可以,但它佔用了不需要的CPU週期。我試圖緩存一次ChannelFactory,但是這導致Ninject無法在HTTP請求結束時刪除對象。

我通過採用一些代碼我發現它包裝的調用WCF客戶端在using語句(使用城堡)以及緩存的ChannelFactory因爲這是令人驚訝的耗時處理這一點。

https://adrianhesketh.wordpress.com/2015/03/17/wcf-client-proxy-creation-performance-with-ninject/

的解決方案來源是這樣的博客:那裏的更多信息https://luisfsgoncalves.wordpress.com/2012/02/28/mixin-up-ninject-castle-dynamic-proxy-and-wcf-part-iii/

其他海報指出,一個好的方法是在一個Func鍵傳遞到你的MVC Web應用程序,因爲這可以防止實例的IPersonService由DI框架創建,但實際上可能並不需要它們。

+0

我不再那麼做了項目,但我有一些copy @ home。我會嘗試申請,並讓你知道。非常感謝你! – 2015-08-19 15:32:28