Rails + Puma + Transfer-Encoding:chunked响应 - 支持与否?

问题描述 投票:1回答:2

组态

  • Rails:4.2.7.1
  • 彪马:3.8.2

--

Transfer-Encoding:  chunked

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

  • 如果是这样,我的责任是什么? 我的控制器应该发出十六进制块大小,\r\n0等?
  • 感觉就像我想要但找不到简单的响应API,如: writewritewriteflush writewritewriteflush close
  • 我已经阅读了100篇关于Rack,猴子补丁和其他精神错乱的帖子
  • 我已经读过Puma和/或Rack修改编码,可能是错误的顺序gzip / deflating
  • 这似乎是一个应该随时可用的简单功能,但我很难过
  • 我已经创建了许多测试,例如self.response_body = Enumerator.newresponse.stream.write等 - 都有类似的结果(通过curl) - Malformed encoding found in chunked-encodingtransfer closed with outstanding read data remaining

有谁能告诉我光明?

ruby-on-rails puma transfer-encoding
2个回答
1
投票

ActionController::Live API提供了您所描述的内容:response.stream.writeresponse.stream.close。 (write会自动刷新一个块;如果这对你不起作用,你需要自己进行缓冲。)

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

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


1
投票

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

Rack规范支持通过the use of the each method在响应对象上或通过the use of hijack进行流式响应。

@matthewd在说明:

ActionController :: Live API提供了您描述的内容......

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

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

但是,这可能会导致相当多的线程并且可能会导致性能变得很高 - 线程数据在内存空间中占用成本(每个线程/客户端1Mb-2Mb),并且随着创建更多线程,上下文切换变得更加昂贵。

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

正确答案不应该是通过单个HTTP请求流式传输数据 - 而是使用本机* WebSockets,SSE或AJAX解决方案。

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

* Native:本地WebSocket / SSE解决方案遵循this Rack proposal,允许服务器处理网络层而不是运行另一个线程/ IO反应器。有关详细信息,请参阅this blog post

© www.soinside.com 2019 - 2024. All rights reserved.