在Sinatra和Thin上下载大文件的高内存消耗

时间:2014-06-16 20:43:29

标签: ruby sinatra rack thin eventmachine

我在Thin上运行Sinatra应用程序。

以下是代码的简化外观:

class StreamApp < Sinatra::Base
  get "/" do
    s3_object = # large S3 object (not loaded into memory)
    stream do |out|
      s3_object.read do |chunk|
        out << chunk
      end
    end
  end
end

随着流媒体的继续,盒子上的内存开始上升到达到最大值并且进程刚好死掉。

我已经阅读了2009年的文章,这是EventMachine和Rack缓存数据的问题,直到整个响应完成。

有没有人看过这个问题或找到了解决方法?

1 个答案:

答案 0 :(得分:2)

在sinatra中流式传输的方式在eventmachine下运行是为了每次调用 out << chunk sinatra计划在eventmachine中调用以发送块。您的代码的问题在于它会阻止事件处理事件循环,直到读取整个文件并完成读取。因此,除了整个数据都在内存中之外,不会发送任何内容。

这可以通过以下方式解决:

get "/" do
s3_object = # large S3 object (not loaded into memory)
  stream :keep_open do |out|
    reader = lambda {
       chunk = s3_object.read
       break if chunk == nil
       out << chunk
       EM::next_tick &reader
    }
    reader.call
  end
end

只要eventmachine准备好就会读取一个块而不阻塞事件循环。当然在这种情况下,s3_object.read只需要返回一个块。