#ruby #sinatra #rack #thin #eventmachine
#ruby #sinatra #стойка #тонкий #eventmachine
Вопрос:
Я запускаю приложение 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 и буферизацией данных в стойке до тех пор, пока весь ответ не будет завершен.
Кто-нибудь видел эту проблему или нашел обходной путь для этого?
Ответ №1:
Способ, которым потоковая передача в sinatra работает в eventmachine, заключается в том, что для каждого вызова out << chunk
sinatra запланирован вызов в eventmachine для отправки фрагмента. Проблема с вашим кодом заключается в том, что он блокирует цикл обработки событий eventmachines до тех пор, пока не будет прочитан весь файл и чтение не будет выполнено. Таким образом, ничего не будет отправлено, пока все данные не окажутся в памяти.
это можно обойти, выполнив что-то вроде:
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 amp;reader
}
reader.call
end
end
это прочитает один фрагмент, как только eventmachine будет готов, не блокируя цикл событий. Конечно, в этом случае s3_object.read нужно возвращать только один фрагмент за раз.
Комментарии:
1. Хм, это имеет смысл. Я попытаюсь воссоздать это, поскольку это была проблема давным-давно, и мы перешли от поддержки этого кода. Тем не менее, я все же хотел бы посмотреть, устраняет ли это проблему.