Asp.net mvc 4 使用WebAPI/MVC4从REST服务调用REST服务

Asp.net mvc 4 使用WebAPI/MVC4从REST服务调用REST服务,asp.net-mvc-4,asp.net-web-api,Asp.net Mvc 4,Asp.net Web Api,我有一个REST服务调用另一个REST服务。两者都使用MVC4WebAPI,在我将其加载之前,调用它们都可以正常工作。简化的代码类似于: public HttpResponseMessage Get() { var url=WebHelpers.CreateUrl(请求“EmployeesGet”); var client=新的HttpClient(); var response=client.GetAsync(url).Result; var retResp=新的HttpResponseMes

我有一个REST服务调用另一个REST服务。两者都使用MVC4WebAPI,在我将其加载之前,调用它们都可以正常工作。简化的代码类似于:

public HttpResponseMessage Get()
{
var url=WebHelpers.CreateUrl(请求“EmployeesGet”);
var client=新的HttpClient();
var response=client.GetAsync(url).Result;
var retResp=新的HttpResponseMessage();
retResp.Content=response.Content;
返回RETREP;
}
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步骤,布尔值&同步完成)+375

如果我返回一个流或仅仅是内容,那么一切正常,但是我不能更改响应的状态码或向响应中添加任何其他元数据

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

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

有几件事

  • 您正在调用将阻止线程的
    .Result
    。这可能是性能问题的一部分。因为您正在执行异步操作,所以应该通过返回
    Task
    并安排一个将内部服务调用的结果转换为外部调用主体的继续操作,使您的操作方法是异步的
  • 我不确定是否简单地将内部调用的
    HttpContent
    复制到外部调用的结果中。您可能希望尝试读取内部流并将其复制到新的外部流中

  • 我建议尝试向控制器中注入一个预先创建的HttpClient实例,并跨请求重新使用它。当HttpClient被释放时,它会关闭并尝试关闭底层连接。根据我对HttpClient源代码的回忆,每次创建新的HttpClient实例时,您都将打开一个新连接。

    我知道我正在阻塞,但对端点的调用通常非常快,这不是问题。此外,我将有一个开发团队在这段代码中工作,我希望保持它的简单。返回任务或流是可行的,但是我无法访问响应来添加元数据。我们有一个自定义标题,我希望能够管理状态代码。我也在考虑复制内容,内容返回的很好,所以看起来很正常,但是有些东西没有释放套接字资源。我想到了这一点。我可以试试。问题是每次调用的url可能不同,每个客户端都有一个特定的站点实例。我会试试这个,看看是否有什么不同。@JayGlynn如果url不同,就不会有问题。HttpClient被构建为可被多个线程重复使用以同时进行调用。这很有帮助,尽管我必须为每个线程使用一个实例(使用Ninject)。我改变了临时港口的限制,这也带来了很大的不同。因为我正在发出另一个请求,所以我使用端口的速度是平时的两倍。