Rails + Puma + Transfer-Encoding:分块响应-是否受支持?

时间:2018-08-06 19:37:16

标签: ruby-on-rails puma transfer-encoding

配置

  • 路轨:4.2.7.1
  • 彪马:3.8.2

-

Transfer-Encoding:  chunked

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

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

有人可以给我看光吗?

2 个答案:

答案 0 :(得分:1)

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

只要您include ActionController::Live(并且注意会影响整个控制器的行为,而不仅仅是一个动作),那么您就应该能够编写流响应,而无需做进一步的工作:您不需要,并且不应设置与分块有关的任何标头等。

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

答案 1 :(得分:1)

@matthewd精彩答案的重要附录:

Rack规范通过响应对象上的the use of the each methodthe use of hijack支持流式响应。

@matthewd正确地说:

  

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

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

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

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

在最坏的情况下,缓慢的each循环会阻塞服务器的线程,削弱服务器的性能并最​​终导致DoS情况。

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

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

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