6

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

这是一个例子。

public void GET(XXXXXRequest request)
{
    System.Threading.Thread.Sleep(2000);
}

然后我用System.Net.Http.HttpClient它来访问它。正如这里所说, HttpClient它的大多数方法都是线程安全的,通过同一 TCP 连接发送 HTTP GET 请求。

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

HttpClient _httpClient = new HttpClient(new WebRequestHandler()
{
    AllowPipelining = true
});

然后我使用以下测试代码在先前的响应之后发送请求

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

smart sniffer中,我确实看到请求是在一个连接中发送的,它就像:

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

现在我将代码更改为即发即弃模式,如下所示。

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

这样请求就可以在不等待之前的响应的情况下发送,我希望请求和响应如下所示

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

这是HTTP 管道,性能非常好。

在此处输入图像描述

但是从我的测试中,我看到每个 HTTP GET 请求都建立了 3 个连接,但它没有按我的预期工作。

关于AllowPipelining财产,MSDN

应用程序使用 AllowPipelining 属性来指示管道连接的首选项。当 AllowPipelining 为真时,应用程序与支持它们的服务器建立管道连接。

那么,我想HttpClient是否支持流水线,问题出在 ServiceStack 中?ServiceStack 中是否有一些选项可以启用 HTTP 流水线?

4

2 回答 2

2

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

于 2015-08-13T17:52:13.283 回答
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等待

于 2017-05-06T01:05:01.210 回答