HttpClient将HTTP GET请求流水线化到ServiceStack API

时间:2015-08-13 11:15:01

标签: servicestack dotnet-httpclient http.sys http-pipelining

首先,我将ServiceStack作为我的服务器,提供RESTful HTTP API。

这是一个例子。

mvn

然后我使用public void GET(XXXXXRequest request) { System.Threading.Thread.Sleep(2000); } 来访问它。 正如here所述,System.Net.Http.HttpClient对于大多数方法来说都是线程安全的,可以通过同一个TCP连接发送HTTP GET请求。

所以我有一个HttpClient的单例实例,如下所示

HttpClient

然后我使用以下测试代码在之前的响应

之后发送请求
HttpClient _httpClient = new HttpClient(new WebRequestHandler()
{
    AllowPipelining = true
});

smart sniffer中,我确实看到请求是通过一个连接发送的,它类似于:

await _httpClient.SendAsync(request1, HttpCompletionOption.ResponseContentRead);
await _httpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead);
await _httpClient.SendAsync(request3, HttpCompletionOption.ResponseContentRead);

现在我将代码更改为fire-and-forget模式,如下所示。

Client -> Request1
Client <- Response1
Client -> Request2
Client <- Response2
Client -> Request3
Client <- Response3

这样就可以在不等待之前的响应的情况下发送请求,并且期望请求&amp;响应如下

_httpClient.SendAsync(request1, HttpCompletionOption.ResponseContentRead);
_httpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead);
_httpClient.SendAsync(request3, HttpCompletionOption.ResponseContentRead);

这是HTTP pipeline,非常适合表现。

enter image description here

但是从我的测试中,我看到每个HTTP GET请求都建立了3个连接,但它不能像我预期的那样工作。

关于Client -> Request1 Client -> Request2 Client -> Request3 Client <- Response1 Client <- Response2 Client <- Response3 proeprty,MSDN

  

应用程序使用AllowPipelining属性来指示   对流水线连接的偏好。当AllowPipelining为true时,a   应用程序与支持的服务器建立流水线连接   它们。

所以,我认为AllowPipelining确实支持流水线操作,问题出在ServiceStack中? ServiceStack中是否有一些选项可以启用HTTP流水线操作?

2 个答案:

答案 0 :(得分:2)

流水线操作在非常低的级别完成,甚至低于IIS(在http.sys内核模式驱动程序中)。虽然我担心我无法解释你所看到的行为,但我可以自信地说ServiceStack并没有支持它。它是一个HttpHandler,它唯一关心的是如何处理请求并返回响应。

答案 1 :(得分:0)

当您使用多个await运算符时,它们会一个接一个地运行,因此HttpClient一次只能获得一个请求,因此无法使用流水线操作。

您可以使用Task.WhenAll()并行运行多个任务:

var responses = await Task.WhenAll(
    _httpClient.SendAsync(request1, HttpCompletionOption.ResponseContentRead),
    _httpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead),
    _httpClient.SendAsync(request3, HttpCompletionOption.ResponseContentRead));

var response1 = responses[0];
var response2 = responses[1];
var response3 = responses[2];

请注意,只等待Task.WhenAll