3

我有一个调用另一个 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 由于系统缺少足够的缓冲区空间或队列已满,无法对套接字执行操作

这会降低我电脑的网络堆栈,直到我重置 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 step, Boolean& completedSynchronously) +375

如果我返回一个流或仅返回内容,则一切正常,但是我无法更改响应的状态代码或将任何其他元数据添加到响应中。

那么,从 Get 方法返回响应的最佳方式是什么,该方法已从另一个调用 REST 服务接收到内容。我不想反序列化/序列化,我真的希望能够在响应中添加一些数据。

更新:在进行负载测试时查看资源监视器时,我看到连接堆积。看来,我不能肯定地说,但似乎从内部对端点的调用Get()并没有释放连接。

4

2 回答 2

2

我建议尝试将预先创建的 HttpClient 实例注入控制器并在请求之间重新使用它。处理 HttpClient 时,它会关闭并尝试关闭底层连接。根据我对 HttpClient 源代码的回忆,每次创建新的 HttpClient 实例时都会打开一个新连接。

于 2012-06-02T03:19:45.870 回答
1

几件事

  1. 您正在调用.Result这将阻塞一个线程。这可能是您的性能问题的一部分。因为您正在执行异步操作,所以您应该通过返回Task<HttpResponseMessage>并安排一个延续将您的内部服务调用的结果转换为外部调用的主体来使您的操作方法异步。
  2. 我不确定是否HttpContent将内部调用的简单复制到外部调用的结果中。您可能想尝试读取内部流并将其复制到新的外部流中。
于 2012-06-01T16:30:09.347 回答