2012-06-01 53 views
3

我有一個調用另一個REST服務的REST服務。兩者都使用MVC 4 WebAPI,並稱它們工作正常,直到我把它放在負載下。簡化的代碼是這樣的:使用WebAPI/MVC從REST服務調用REST服務4

public HttpResponseMessage Get() 
{ 
    var url = WebHelpers.CreateUrl(Request, "EmployeesGet"); 
    var client = new HttpClient(); 
    var response = client.GetAsync(url).Result; 
    var retResp = new HttpResponseMessage(); 
    retResp.Content = response.Content; 
    return retResp; 
} 

WebHelper.CreateUrl構造端點URL。 當我穿上,100個用戶模擬負載,我得到約16000請求,我得到一個插座異常:

SocketException由於系統缺乏足夠的緩衝區空間或者因爲無法執行套接字上的操作一個隊列已滿

這需要我的電腦的網絡堆棧,直到我重置IIS。 我想也許我需要更積極的清理,所以我處置HttpClient沒有任何效果。然後我想我需要處理從端點獲得的響應,因爲一旦我獲得了內容,我就不再需要它了。奇怪的是,我然後得到一個異常,說一個處置對象不能被引用。這是來自MVC框架。異常如下:

[ObjectDisposedException:無法訪問處置的對象。 對象名:' System.Net.Http.StreamContent '] System.Web.Http.WebHost.HttpControllerHandler.EndProcessRequest(IAsyncResult的結果)49019 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute(。 )469 System.Web.HttpApplication.ExecuteStep(IExecutionStep一步,布爾& completedSynchronously)+375

如果我回到流或僅僅是內容的東西做工精細,但我不能改變響應狀態編碼或添加任何其他元數據到響應。

那麼從Get方法返回響應的最佳方式是從另一個REST服務調用中接收內容。我不想反序列化/序列化,我真的希望能夠將一些數據添加到響應中。

更新:在進行負載測試時查看資源監視器時,發現連接堆疊在一起。看起來,我不能肯定地說,但看起來從Get()內部呼叫端點不是釋放連接。

回答

2

我會建議嘗試向控制器注入一個預先創建的HttpClient實例並跨請求重新使用它。當處理HttpClient時,它將關閉並嘗試關閉底層連接。從我回想起的HttpClient源代碼中,您將在每次創建新的HttpClient實例時打開一個新連接。

+0

我想到了。我可以試試。問題是每次調用的URL可能不同,每個客戶端都有一個特定的站點實例。我會嘗試一下,看看它是否有所作爲。 – JayGlynn

+0

@JayGlynn如果url不同,應該不會有問題。 HttpClient被構建爲被多個線程重複使用以進行同時呼叫。 –

+0

這有幫助,但我不得不每個線程使用一個實例(使用Ninject)。我改變了短暫端口的限制,這也造成了很大的不同。由於我正在提出另一個請求,因此我使用端口的速度是通常的兩倍。 – JayGlynn

1

幾件事情

  1. 要調用.Result將阻塞線程。這可能是你的性能問題的一部分。由於您正在執行異步操作,因此您應該通過返回Task<HttpResponseMessage>使您的操作方法變爲異步,並計劃將內部服務調用的結果轉換爲外部調用正文的延續。
  2. 我不確定將內部呼叫的HttpContent複製到外部呼叫的結果中。您可能想要嘗試讀取內部流並將其複製到新的外部流中。
+0

我知道我阻止了,但對端點的呼叫通常非常快,這不是問題。除此之外,我還會有一個開發團隊在這個代碼中工作,我想保持簡單。返回一個Task或者一個流程,但是我沒有權限訪問添加元數據的響應。我們有一個自定義標題,我希望能夠管理狀態碼。我想知道複製內容的好處,內容返回正常,所以它似乎正在工作,但有些東西不釋放套接字資源。 – JayGlynn