Два ответа:
Ленивый ответ: просто используйте блокирующую запись.EM уже передает вам отдельные куски данных, а не одну гигантскую строку.Так что ваш пример реализации может быть немного не так.Вы уверены, что хотите создать новый временный файл для каждого куска, который EM вручает вам?Тем не менее, я продолжу исходить из предположения, что ваш пример кода работает так, как задумано.
По общему признанию, ленивый подход зависит от устройства, на которое вы пишете, но пытаясь одновременно записать несколько больших потоков на диск вТо же самое может стать серьезным узким местом, и вы все равно потеряете свои преимущества, связанные с наличием сервера на основе событий.Вы просто получите жонглирование дисковым поиском повсюду, производительность ввода-вывода упадет, как и производительность вашего сервера.Одновременная работа со многими вещами - это нормально с ОЗУ, но как только вы начнете работать с блочными устройствами и планированием ввода-вывода, вы столкнетесь с узкими местами производительности независимо от того, что вы делаете.Возможно, вы захотите сделать несколько длинных операций записи на диск в то же время, когда вы хотите получить ответы с низкой задержкой на другие запросы, не связанные с IO.Так что, возможно, хороший ответ:
Используйте defer .
require 'rubygems'
require 'tempfile'
require 'eventmachine'
module ExampleServer
def receive_data(data)
operation = proc do
begin
f = Tempfile.new('random')
f.write(data)
ensure
f.close
end
end
callback = proc do
puts "I wrote a file!"
end
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine::start_server "127.0.0.1", 8081, ExampleServer
puts 'running example server on 8081'
}
Да, это действительно использует многопоточность.Это действительно не так уж и плохо в этом случае: вам не нужно беспокоиться о синхронизации между потоками, потому что EM достаточно хорош, чтобы справиться с этим для вас.Если вам нужен ответ, используйте обратный вызов, который будет выполнен в главном потоке реактора после завершения рабочего потока.Кроме того, GIL не является проблемой для этого случая, так как вы имеете дело с блокировкой ввода-вывода и не пытаетесь достичь параллелизма ЦП.
Но если вы намеревались записать все в одно и то жефайл, вам нужно быть осторожным с отсрочкой, так как проблема синхронизации возникнет, поскольку ваши потоки, вероятно, будут пытаться записать в тот же файл в то же время.