2014-06-16 48 views
3

我在Thin上運行Sinatra應用程序。在Sinatra和Thin上下載大文件的高內存消耗

下面的代碼的簡化一下:

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緩衝數據的問題,直到整個響應完成。

有沒有人看到這個問題或找到解決方法?

回答

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只需要返回一個塊。

+0

嗯,這是有道理的。我會嘗試重新創建它,因爲這是很久以前的問題,我們已經從維護這些代碼開始。不過,我仍然想看看是否能解決這個問題。 –