) так, чтобы он работал в отдельном потоке (но я не знаю, насколько эффективным является это решение).

ратил несколько дней на то, чтобы найти примеры не-эхо-серверов для eventmachine, но, похоже, их просто нет. Допустим, я хочу написать сервер, который принимает файл и записывает его в Tempfile:

require 'rubygems'
require 'tempfile'
require 'eventmachine'

module ExampleServer

  def receive_data(data)
    f = Tempfile.new('random')
    f.write(data)
  ensure
    f.close
  end

end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, ExampleServer
  puts 'running example server on 8081'
}

Запись в файл блокирует реактор, но я не понимаю, как это сделать, 'стиль Eventmachine'. Должен ли я читать данные порциями и записывать каждый порции на диск в блоке Em.next_tick?

Спасибо за любую помощь Андреас

Ответы на вопрос(4)

Каков наилучший способ чтения файлов в приложении на основе EventMachine? (но я хотел знать, как эффективно читать файлы). Кажется, что не существует никакого неблокирующего файлового API, поэтому лучшее, что вы можете сделать, это написать короткие пакеты сnext_tick или отложить написание (сdefer) так, чтобы он работал в отдельном потоке (но я не знаю, насколько эффективным является это решение).

файлы плохо реагируют на выбор интерфейсов. Если вам нужно что-то более эффективное, чем запись IO # (что маловероятно), то вы можете использоватьEIO.

EIO действительно только слегка разблокирует реактор и предоставит вам небольшую буферизацию. Если определенные задержки являются проблемой, или у вас действительно медленные диски, это может быть полезно. В большинстве других случаев это, вероятно, просто куча усилий для небольшого преимущества.

Ленивый ответ: просто используйте блокирующую запись. EM уже передает вам отдельные куски данных, а не одну гигантскую строку. Так что ваш пример реализации может быть немного не так. Вы уверены, что хотите создать новый временный файл для каждого куска, который EM вручает вам? Однако я продолжу, предполагая, что ваш пример кода работает так, как задумано.

По общему признанию, ленивый подход зависит от устройства, на которое вы пишете, но попытка одновременно записать несколько больших потоков на диск будет основным узким местом, и вы все равно потеряете свои преимущества, связанные с наличием сервера на основе событий. Вы просто получите жонглирование дисковым поиском повсюду, производительность ввода-вывода упадет, как и производительность вашего сервера. Одновременная работа со многими вещами - это нормально с ОЗУ, но как только вы начнете работать с блочными устройствами и планированием ввода-вывода, вы столкнетесь с узкими местами производительности независимо от того, что вы делаете.

Тем не менее, я полагаю, что вам может потребоваться выполнить несколько длительных операций записи на диск в то же время, когда вы хотите получать ответы с низкой задержкой на другие, не связанные с вводом-выводом запросы. Итак, возможно, хороший ответ:

использованиеоткладывать.

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 - это не проблема для этого случая, так как вы имеете дело с блокировкой ввода-вывода и не пытаетесь достичь параллелизма ЦП.

Но если вы намеревались записать все в один и тот же файл, вам нужно быть осторожным с отсрочкой, поскольку проблема синхронизации возникнет, поскольку ваши потоки, вероятно, попытаются выполнить запись в один и тот же файл одновременно.

документыкажется, вам просто нужноприкреплять файл (хотя, как вы отмечаете, это может быть недействительным, кажется, что вариант заключается в использовании File.write / ie blocking ...) иsend_data .

Хотя я думал, что вы не можете смешивать блокирующий / неблокирующий ввод-вывод с EM :(

Учитывая, что исходные данные являются сокетом, я думаю, что он будет обрабатываться EventMachine.

Возможно вопрос длягруппа Google...

~ Крис

 Andreas10 янв. 2011 г., 14:01
Крис, спасибо за твой ответ.Этот ответ по tmm1 противоречит тому, что говорят документы (или я неправильно понимаю либо). В основном я пытаюсь сделать очень простую передачу файлов (чтение из сокета и запись на диск) ...

Ваш ответ на вопрос