Rails + Puma + 传输编码:分块响应 - 支持与否?

Rails + Puma + Transfer-Encoding: chunked response - supported or not?

配置

--

Transfer-Encoding:  chunked

我一直无法完成这项工作,也找不到明确的答案:在上面的配置中,我想将大量数据流式传输到客户端(在响应中)- 这是否受支持?

任何人都可以告诉我灯吗?

ActionController::Live API 完全符合您的描述:response.stream.writeresponse.stream.close。 (write 自动刷新一个块;如果这对你不起作用,你需要自己做缓冲。)

只要你include ActionController::Live(注意这会影响整个控制器的行为,而不仅仅是一个动作),你应该能够毫不费力地编写流式响应:你不需要,并且不应设置与分块相关的任何 headers 等。

附加参考:http://tenderlovemaking.com/2012/07/30/is-it-live.html

@matthewd 精彩回答的重要补充:

Rack 规范支持通过 the use of the each method on the response object or through the use of hijack 的流式响应。

@matthewd 说得对:

The ActionController::Live API offers exactly what you describe...

但是,实现要么劫持套接字,要么使用 Rack 规范的 "hack" 和 each 方法。

最好的情况是实现劫持套接字并在新线程上运行它(这是它通常应该做的,AFAIK)。

但是,这可能会导致大量线程,并且 可能会导致性能变差 - 线程在内存中的成本 space 用于堆栈数据(每个线程 1Mb-2Mb / 客户端)和上下文切换变得更加昂贵,因为更多的线程被创建。

在最坏的情况下,缓慢的 each 循环会阻塞服务器的线程,使服务器瘫痪并最终导致 DoS 情况。

正确的答案应该不是通过单个 HTTP 请求流式传输数据 - 请改用 native* WebSockets、SSE 或 AJAX 解决方案。

另一种半正确的方法是将所有数据保存到一个临时文件中,并使用支持静态文件流的服务器发送文件到 Ruby 层之外(例如 iodine)或代理(例如nginx)。

* 本机:本机 WebSocket / SSE 解决方案遵循 this Rack proposal and allows the server to handle the network layer rather than running another thread / IO reactor. See this blog post 以获取更多详细信息。