2017-05-09 114 views
1

我有一個簡單的REST服務,並通過WebChannelFactory用WCF調用它。 當我將綁定設置爲使用TransferMode.Streamed時,連接似乎沒有被重用,並且在多次請求後(通常爲ServicePointManager.DefaultConnectionLimit,但有時還有幾次),我沒有連接(請求調用掛起,然後I得到一個超時例外)。當TransferMode = Streamed時用盡連接

[ServiceContract] 
    public interface IInviteAPI { 
     [OperationContract] 
     [WebGet(UriTemplate = "invites/{id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
     Invite GetInvite(string id); 
    } 

    [STAThread] 
    static int Main(string[] args) { 
     ServicePointManager.DefaultConnectionLimit = 16; // make a larger default 
     WebHttpBinding binding = new WebHttpBinding(); 
     binding.TransferMode = TransferMode.Streamed; 

     try { 
      WebChannelFactory<IInviteAPI> factory = new WebChannelFactory<IInviteAPI>(binding, new Uri("http://example.com/invite")); 
      IInviteAPI channel = factory.CreateChannel(); 
      for (int i = 0; i < 100; i++) { 
       Invite data = channel.GetInvite("160"); // fails on i==16 
      } 
      ((IChannel)channel).Close(); 
     } 
     catch (Exception ex) { 
      Debug.WriteLine(ex); 
     } 
     return 0; 
    } 

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9969999.

有關於未關閉通道的淨多很多帖子 - 這裏這不是問題,因爲我只是多次在同一頻道發表了同樣的要求。

  • 如果我刪除binding.TransferMode = TransferMode.Streamed;行,它完美的作品。
  • 我還可以創建和關閉循環內的通道,它具有相同的問題

     for (int i = 0; i < 100; i++) { 
          IInviteAPI channel = factory.CreateChannel(); 
          Invite data = channel.GetInvite("160"); // fails on i==20 
          ((IChannel)channel).Close(); 
         } 
    
  • 有趣的是,如果我在循環中添加GC.Collect(),它的工作!在通過.Net代碼進行詳細追蹤之後,這似乎是因爲僅在ServicePointManager中以弱引用存在。調用GC.Collect然後完成ServicePoint,並關閉所有當前連接。

有什麼我失蹤?如何保持TransferMode.Streamed並能夠多次撥打該服務,並使用合理的ServicePointManager.DefaultConnectionLimit

(我需要TransferMode.Streamed因爲對服務的其他呼叫是用於傳輸數據的龐大檔案高達1GB)

更新
如果我運行netstat -nb我可以看到,有16個連接處於ESTABLISHED狀態的服務器。大約30秒後,它們變爲CLOSE_WAIT(大概是服務器關閉空閒連接),但是這些CLOSE_WAIT連接之後永遠不會消失,無論我設置超時的時間有多大。

這似乎是.Net中的一個錯誤:連接應該被重新使用,但不是。第17個要求正在永遠排隊。

+0

當調用一個WCF客戶端流WCF服務,該連接不會關閉:

可以incrase併發連接數限制或。關閉代理不會關閉連接。 –

+0

在你的情況下,你似乎是反序列化對內存中的Invite對象的響應。我想這意味着你不需要TransferMode.Streamed,或者你應該找到另一種方法。 –

+0

只有使用WCF進行流式傳輸的特定情況纔有效。請參閱https://msdn.microsoft.com/en-us/library/ms733742(v=vs.110).aspx觀看MessageContract。唯一的身體成員應該是流。如果你不能這樣做,看看HttpClient。 –

回答

0

我知道對於WCF配置的默認限制,併發性和可伸縮性存在20個併發入站連接限制。直到處置響應流

for (int i = 0; i < 100; i++) { 
    Invite data = channel.GetInvite("160"); 
    Thread.Sleep(1000); // prevent to concurrency connection to wcf service 
} 
+0

問題不在於併發連接。所有請求都在串行執行 - 只需要一個連接。 – mikek

+0

此外,服務器不是WCF服務,它是基於Java的REST服務,並沒有併發限制。這個限制純粹是在客戶端。 – mikek

相關問題