配置
-
Transfer-Encoding: chunked
我一直无法完成这项工作,也找不到确切的答案:在上述配置中,我想向客户端(在响应中)流式传输大量数据-是否支持?
\r\n
,0
等?write
,write
,write
,flush
write
,write
,write
,flush
close
self.response_body = Enumerator.new
和response.stream.write
等-都具有相似的结果(通过curl
)-Malformed encoding found in chunked-encoding
或transfer closed with outstanding read data remaining
有人可以给我看光吗?
答案 0 :(得分:1)
ActionController::Live API提供了您所描述的内容:response.stream.write
和response.stream.close
。 (write
自动刷新一个块;如果不适合您,则需要自己进行缓冲。)
只要您include ActionController::Live
(并且注意会影响整个控制器的行为,而不仅仅是一个动作),那么您就应该能够编写流响应,而无需做进一步的工作:您不需要,并且不应设置与分块有关的任何标头等。
答案 1 :(得分: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)发送该文件
*本机:this Rack proposal之后是本机WebSocket / SSE解决方案,它允许服务器处理网络层,而不是运行另一个线程/ IO反应器。有关更多详细信息,请参见this blog post。