我有一个调用另一个 REST 服务的 REST 服务。两者都使用 MVC 4 WebAPI 并且调用它们工作正常,直到我将其置于负载之下。简化的代码是这样的:
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 个用户,我收到大约 16,000 个请求,并且出现套接字异常:
SocketException An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full
这会关闭我的电脑的网络堆栈,直到我重置 IIS。
我想也许我需要更主动地清理,所以我处理了 HttpClient
但没有任何效果。然后我想我需要处理从端点获得的响应,因为一旦我获得了内容,我就不再需要它了。奇怪的是,然后我得到一个异常,表明无法引用已处置的对象。这是来自 MVC 框架。异常如下:
[ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Http.StreamContent'.] System.Web.Http.WebHost.HttpControllerHandler.EndProcessRequest(IAsyncResult result) +49019 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +469 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +375
如果我返回流或仅返回内容,一切正常,但我无法更改响应的状态代码或向响应添加任何其他元数据。
那么,从 Get 方法返回响应的最佳方式是什么?该方法已从对 REST 服务的另一个调用接收到内容。我不想反序列化/序列化,我真的希望能够向发出的响应添加一些数据。
更新:在进行负载测试时查看资源监视器时,我看到连接在堆积。看起来,我不能肯定地说,但似乎从 Get()
内部对端点的调用没有释放连接。
最佳答案
我建议尝试将预先创建的 HttpClient 实例注入(inject) Controller 并在请求中重新使用它。当 HttpClient 被处置时,它会关闭并尝试关闭底层连接。根据我对 HttpClient 源代码的记忆,每次创建新的 HttpClient 实例时都会打开一个新连接。
关于asp.net-mvc-4 - 使用 WebAPI/MVC 4 从 REST 服务调用 REST 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10852183/