Rails 3.1 将支持 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 浏览器在接收到文档内容时会解析它。当它们找到引用的资源(例如图片、样式表或脚本)时,就会发起请求来获取它们。这会 并行地 发生,即在文档接收和处理的 同时,无论内容是否分块发送。
浏览器对允许进行的并发请求数量有限制,有一个全局限制(通常是 30 多个),还有一个按域的限制(现在通常是 4 或 6 个),但在这些限制范围内,获取资源的请求会在内容解析时发生。
现代客户端甚至不会像旧客户端那样等待 JavaScript 文件,它们实现了扫描器,可以提前查找资源节点并请求它们。例如,这就是 WebKit 的预加载扫描器。
趣闻:在研究这个的时候,我意外地发现,如果 MIME 类型不明确(例如,“text/html”但没有显式指定字符集),那么 Web 浏览器会缓冲 1 KB 的数据,而不发起资源请求,以便能够查看内容并 做出一个合理的猜测。
流式传输并不能减少延迟,也不能减少动态响应的生成时间。但是,由于应用程序可以立即发送内容,而不是等待整个响应被渲染,所以客户端能够更早地请求资源。特别地,如果您发送 HTML 文档的头部,CSS 和 JavaScript 文件将被并行获取,同时服务器仍在生成内容。其结果是页面加载得更快。
流式传输仍在为 Rails 3.1 进行完善,预计未来还将有一篇文章介绍其在 Ruby on Rails 应用程序中的实际应用。
Tony Gentilcore 提供了他的内部指导,非常感谢 Tony!另外,也非常感谢 Browserscope 项目 提供的非常有用的表格。