我有一個簡單的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個要求正在永遠排隊。
當調用一個WCF客戶端流WCF服務,該連接不會關閉:
可以incrase併發連接數限制或。關閉代理不會關閉連接。 –
在你的情況下,你似乎是反序列化對內存中的Invite對象的響應。我想這意味着你不需要TransferMode.Streamed,或者你應該找到另一種方法。 –
只有使用WCF進行流式傳輸的特定情況纔有效。請參閱https://msdn.microsoft.com/en-us/library/ms733742(v=vs.110).aspx觀看MessageContract。唯一的身體成員應該是流。如果你不能這樣做,看看HttpClient。 –