2011 年 4 月 18 日,星期一

为什么使用 HTTP 流式传输?

由 fxn 发布

Rails 3.1 将支持 HTTP 流式传输,也称为分块响应,本文将对此进行解释。

什么是 HTTP 流式传输?

普通的动态 HTTP 响应需要 Content-Length 头部。它们的执行流程如下:

HTTP request -> dynamic content generation -> HTTP response

这三个步骤是串行的,因为通常您需要生成内容才能知道其大小,从而填写响应的 Content-Length 头部。

HTTP 提供了一种替代方案,可以允许在数据生成时就发送数据,这被称为 分块传输编码。这就是我们近期提交中提到的“流式传输”。

流式传输的响应没有 Content-Length 头部。相反,它们有一个值为“chunked”的 Transfer-Encoding 头部,以及一个由一系列块组成的正文,每个块的大小都 precedes 其内容。详细细节省略。

这是一个来自维基百科的例子

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1C
and this is the second one

3
con
8
sequence
0

重点是,您可以在获得数据块后立即将其发送到套接字,无需等待整个内容生成完毕。

Web 浏览器何时获取资源?

Web 浏览器在接收到文档内容时会解析它。当它们找到引用的资源(例如图片、样式表或脚本)时,就会发起请求来获取它们。这会 并行地 发生,即在文档接收和处理的 同时,无论内容是否分块发送。

浏览器对允许进行的并发请求数量有限制,有一个全局限制(通常是 30 多个),还有一个按域的限制(现在通常是 4 或 6 个),但在这些限制范围内,获取资源的请求会在内容解析时发生。

现代客户端甚至不会像旧客户端那样等待 JavaScript 文件,它们实现了扫描器,可以提前查找资源节点并请求它们。例如,这就是 WebKit 的预加载扫描器

趣闻:在研究这个的时候,我意外地发现,如果 MIME 类型不明确(例如,“text/html”但没有显式指定字符集),那么 Web 浏览器会缓冲 1 KB 的数据,而不发起资源请求,以便能够查看内容并 做出一个合理的猜测

那么流式传输的好处是什么?

流式传输并不能减少延迟,也不能减少动态响应的生成时间。但是,由于应用程序可以立即发送内容,而不是等待整个响应被渲染,所以客户端能够更早地请求资源。特别地,如果您发送 HTML 文档的头部,CSS 和 JavaScript 文件将被并行获取,同时服务器仍在生成内容。其结果是页面加载得更快。

后续

流式传输仍在为 Rails 3.1 进行完善,预计未来还将有一篇文章介绍其在 Ruby on Rails 应用程序中的实际应用。

感谢

Tony Gentilcore 提供了他的内部指导,非常感谢 Tony!另外,也非常感谢 Browserscope 项目 提供的非常有用的表格。