2015-08-13 50 views
1

我想弄清楚我們正在使用我們大量使用的WCF服務中的一個問題。它偶爾會變得無響應,從而使我們的幾個內部網站依賴於服務無法使用。如何檢測WCF客戶端何時無法正常關閉?

我們懷疑這是因爲一個或多個使用網站未能正確關閉連接,所以我們正在限制服務上允許的併發連接數。然而,我們沒有可行的方法來確定哪一個,因爲在幾個tfs存儲庫中有這麼多。

總之,當客戶端在wcf代理上調用Close()時,如何檢測服務?或者,相反,如何在服務方法完成後檢測http連接是否仍處於打開狀態?

我已經建立了我的本地工作站上測試服務端和客戶端,並試圖以下,雖然沒有相當的工作:

測試服務:

public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     return string.Format("You entered: {0}", value); 
    } 
} 

測試客戶端:

class Program 
{ 
    static void Main(string[] args) 
    { 
     ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(); 
     Console.WriteLine(client.GetData(0)); 
     Console.ReadKey(); 
     client.Close(); 
     Console.WriteLine("Closed."); 
     Console.ReadKey(); 
    } 
} 

運行netstat顯示,即使在client.Close()之後,連接保持打開狀態(也許我只是誤解了netstat的輸出)。

perfmon性能計數器(在添加ServiceModelService 4.0.0.0之後)報告服務調用甚至在執行client.Close()之前完成。在服務調用之後,client.Close()之前和之後的計數器都沒有變化。

接下來,我試圖聽OperationContext.Current.Channel.Closed事件(以及閉幕式,並斷陷):

public class Service1 : IService1 
{ 
    public string GetData(int value) 
    { 
     OperationContext.Current.Channel.Faulted += Channel_Faulted; 
     OperationContext.Current.Channel.Closing += Channel_Closing; 
     OperationContext.Current.Channel.Closed += Channel_Closed; 
     return string.Format("You entered: {0}", value); 
    } 

    void Channel_Faulted(object sender, EventArgs e) 
    { 
     // Breakpoint 
    } 

    void Channel_Closing(object sender, EventArgs e) 
    { 
     // Breakpoint 
    } 

    void Channel_Closed(object sender, EventArgs e) 
    { 
     // Breakpoint 
    } 
} 

但沒有斷點的,我把事件處理程序比金堅擊中。

我也嘗試在Global.asax的Session_Start和Session_End事件中放置斷點。 Session_Start會觸發,但Session_End永遠不會(雖然我不知道會話是否與http連接是否存在有關)。我對wcf(我之前寫過一些非常基本的服務)有點新,所以我覺得我在這個問題上有點過頭了,挖掘出我不瞭解的部分(例如,我不知道今天之前存在OperationContext)。

+0

您的服務是無狀態還是有狀態? – jtabuloc

+0

我們遇到問題的服務是無狀態的。 – kgundlach

+0

該死的,stackoverflow不是它曾經是。如果我在2008年問過這個問題,我現在會有十幾個答案。 – kgundlach

回答

0

您應該在呼叫您的服務時處理異常情況,否則渠道可能無法正常關閉。

例如:from here

WCFServiceClient c = new WCFServiceClient(); 

    try 
    { 
      c.HelloWorld(); 
    } 
    catch 
    { 
      c.Abort(); 
      throw; 
    } 
    finally 
    { 
      c.Close(); 
    } 

(還有與 '使用' 如果優選的一個例子)。

也看看here

+0

我發佈的只是一個測試客戶端。我們的大多數應用程序都會應用您所說的模式但是,.NET 3.5框架中存在一個錯誤,其中有一些可以由代理引發的異常,但仍然保持連接在服務端打開。在這種情況下,在中止之後調用Close是完全沒有用的,因爲在Abort()之後,客戶端無法與服務器通信。我們的許多應用都在3.5以上,並且由於各種商業原因,無法立即升級。 – kgundlach

相關問題