感谢Google和Stack Overflow,我想我理解了常规HTTP流水线和HTTP多路复用之间的区别(例如,使用SPDY),因此我在下面的图表中显示了基于三个常规HTTP请求的流水线和多路复用之间的差异.
我的两个问题是:
许多(如果不是全部)现代浏览器都没有使用流水线HTTP请求.理论上,流水线操作应该通过减少获取网站所需的往返时间来加快请求.
根据HTTP标准,所有服务器都必须处理流水线请求,因此问题不应该是服务器上缺乏支持.
我已经看到了一些安全问题,例如,如果客户端将尽可能多的流水线请求推送到服务器性能密集的URL,忽略可能收到的任何答案,则会出现第7层DoS攻击.
这将是在服务器上关闭流水线支持的原因(违反标准),但我找不到任何理由在客户端关闭它.
但是,默认情况下,它会在Android浏览器和Chrome移动设备上启用.
为什么Chrome,Firefox,IE,Opera和Safari在桌面(有时是移动)版本中没有使用流水线式HTTP请求?关闭它背后的理由是什么?
firefox internet-explorer google-chrome http http-pipelining
我试图了解什么是HTTP流水线和HTTP保持活动连接,并尝试在这两个主题和Server Sent事件技术之间建立连接.
据我所知,当建立的一次TCP连接用于逐个发送多个HTTP请求时, HTTP保持连接是HTTP 1.1使用TCP的默认方式. HTTP流水线操作是客户端向服务器发送请求的功能,而使用相同的TCP连接尚未收到对先前请求的响应,通常不会在浏览器中用作默认方式.
我的问题:
1)如果可以使用一个TCP连接一个接一个地向服务器发送多个请求 - 客户端如何区分响应?我猜客户端正在使用FIFO顺序发送服务器的响应?
2)为什么非幂等请求(如POST请求)不应该被流水线化(根据维基百科)?
3)Web服务器的局限性是什么:可能的开放TCP连接数量是多少?如果是,那么如果某些客户端持有保持活动连接,则其他客户端无法建立连接,这可能会导致问题,对吧?
4)Server Sent Events正在使用keep-alive连接,但据我所知,SSE没有使用流水线技术.相反,他们设法处理对一个请求的多个响应,或者他们只是在下一个事件响应到达时发送另一个请求.哪种猜测是正确的?
5)一个TCP连接意味着一个插座?一个套接字意味着一个TCP连接?关闭/打开套接字意味着关闭/打开TCP连接?
首先,我有ServiceStack作为我的服务器,它提供RESTful HTTP API.
这是一个例子.
public void GET(XXXXXRequest request)
{
System.Threading.Thread.Sleep(2000);
}
Run Code Online (Sandbox Code Playgroud)
然后我System.Net.Http.HttpClient
用来访问它.正如这里所说的, HttpClient
对于大多数方法来说,通过相同的TCP连接发送HTTP GET请求是线程安全的.
所以我有一个HttpClient的单例实例,如下所示
HttpClient _httpClient = new HttpClient(new WebRequestHandler()
{
AllowPipelining = true
});
Run Code Online (Sandbox Code Playgroud)
然后我使用以下测试代码在上一次响应之后发送请求
await _httpClient.SendAsync(request1, HttpCompletionOption.ResponseContentRead);
await _httpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead);
await _httpClient.SendAsync(request3, HttpCompletionOption.ResponseContentRead);
Run Code Online (Sandbox Code Playgroud)
在智能嗅探器中,我确实看到请求是通过一个连接发送的,它类似于:
Client -> Request1
Client <- Response1
Client -> Request2
Client <- Response2
Client -> Request3
Client <- Response3
Run Code Online (Sandbox Code Playgroud)
现在我将代码更改为fire-and-forget模式,如下所示.
_httpClient.SendAsync(request1, HttpCompletionOption.ResponseContentRead);
_httpClient.SendAsync(request2, HttpCompletionOption.ResponseContentRead);
_httpClient.SendAsync(request3, HttpCompletionOption.ResponseContentRead);
Run Code Online (Sandbox Code Playgroud)
这样就可以在不等待之前的响应的情况下发送请求,我希望请求和响应如下所示
Client -> Request1
Client -> Request2
Client -> …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 PHP cURL HTTP Pipelining 功能通过单个 TCP 连接执行多个请求。请参阅此页面http://www.php.net/manual/en/function.curl-multi-setopt.php我通过添加以下内容为 curl_multi_exec() 启用流水线:
curl_multi_setopt($mh, CURLMOPT_PIPELINING, 1);
我不想在此处发布大量源代码列表,但您可以在此处从我的 github 轻松查看或检出完整示例https://github.com/anovikov1984/pipelining-example
为了监控 TCP 连接,我在另一个控制台会话中使用了“netstat -t -u -c”命令。
在我上面提到的 repo 中,有两个脚本。一种用于 Ruby,一种用于 PHP。Ruby 版本可以正常工作,并且只为 3 个 GET 请求打开单个 TCP 连接。但是 PHP cURL 版本打开的 TCP 连接与传递给 curl_multi_exec() 函数的 cURL 句柄的数量一样多。
我究竟做错了什么?
Node.js 内置的 HTTP 客户端似乎不支持流水线请求。但是,我突然想到可以创建一个在后台设置流水线的代理。将响应数据恢复为应有的方式可能会出现问题,但也许代理可以伪造一些套接字对象以使 HTTP 客户端正常工作?
这已经完成了吗?或者,是否有替代 HTTP 客户端可以直接替代支持流水线的主要客户端?(最终,我想将它与 AWS SDK 一起使用,因此它需要兼容。)
我刚刚阅读了关于HTTP流水线的维基百科文章,从图中可以看出,响应可以在一个连接上同时发送.我是否误解了图表或允许这样做?
服务器必须按照收到请求的顺序发送对这些请求的响应.
虽然该停止短的明确排除并发响应,它没有提到要确保响应不仅要以正确的顺序有关系的请求开始,但也完成正确的顺序.
我也无法想象处理并发响应的实用性 - 客户如何知道接收数据应用于哪个响应?
因此,我对RFC的解释是,虽然可以在处理对第一个请求的响应时进行其他请求,但是客户端不允许发送并发请求或服务器在同一连接上发送并发响应.
它是否正确?我附上了一张图表来说明我的解释.
它可以防止我提到的问题发生,但它似乎与维基百科中的图表完全一致.
http ×6
curl ×1
firefox ×1
http.sys ×1
keep-alive ×1
multiplexing ×1
node.js ×1
php ×1
rfc2616 ×1
servicestack ×1
spdy ×1