组态
--
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
有谁能告诉我光明?
ActionController::Live API提供了您所描述的内容:response.stream.write
和response.stream.close
。 (write
会自动刷新一个块;如果这对你不起作用,你需要自己进行缓冲。)
只要你include ActionController::Live
(并注意影响整个控制器的行为,而不仅仅是一个动作),你应该能够不费力地写一个流响应:你不需要,也不应该设置任何标题等与分块有关。
@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。