Синатра многопоточная? - PullRequest
45 голосов
/ 08 июня 2011

Sinatra многопоточный? Я читал еще, где это "sinatra является многопоточным по умолчанию", что это значит?

Рассмотрим этот пример

get "/multithread" do
  t1 = Thread.new{
    puts "sleeping for 10 sec"
    sleep 10
    # Actually make a call to Third party API using HTTP NET or whatever.
  }
  t1.join
  "multi thread"
end

get "/dummy" do
  "dummy"
end

Если я получаю доступ к «/ multithread» и «/ dummy» впоследствии в другой вкладке или браузере, то ничего не может быть подано (в этом случае в течение 10 секунд) до тех пор, пока не будет завершен запрос «/ multithread». В случае зависания активности приложение перестает отвечать на запросы.

Как мы можем обойти это без порождения другого экземпляра приложения?

Ответы [ 5 ]

91 голосов
/ 08 июня 2011

tl; dr Sinatra хорошо работает с потоками, но вам, вероятно, придется использовать другой веб-сервер.

Сам Синатра не навязывает какую-либо модель параллелизма, он даже не обрабатывает параллелизм. Это делается обработчиком Rack (веб-сервером), таким как Thin, WEBrick или Passenger. Сам Sinatra является поточно-ориентированным, что означает, что если ваш обработчик Rack использует несколько потоков для запросов к серверу, он работает просто отлично. Однако, поскольку Ruby 1.8 поддерживает только зеленые потоки, а Ruby 1.9 имеет глобальную блокировку виртуальной машины, потоки не так широко используются для параллелизма, так как в обеих версиях потоки не будут работать действительно параллельно. Однако завещание будет на JRuby или на предстоящем Rubinius 2.0 (обе альтернативные реализации Ruby).

Большинство существующих обработчиков Rack, использующих потоки, будут использовать пул потоков для повторного использования потоков вместо того, чтобы фактически создавать поток для каждого входящего запроса, поскольку создание потоков не является бесплатным, особенно на 1.9, где потоки отображают 1: 1 на собственные потоки. Зеленые потоки имеют гораздо меньше накладных расходов, поэтому волокна, которые в основном представляют собой совместно запланированные зеленые потоки, используемые в вышеупомянутой синатра-синхронии, стали так популярны в последнее время. Вы должны знать, что любое сетевое взаимодействие должно проходить через EventMachine, поэтому вы не можете использовать гем mysql, например, для общения с вашей базой данных.

Волокна хорошо масштабируются для интенсивной обработки в сети, но с треском проваливаются при тяжелых вычислениях. У вас меньше шансов столкнуться с условиями гонки, что является распространенной ошибкой при параллельности, если вы используете волокна, поскольку они выполняют переключение контекста только в четко определенных точках (с синхронизацией, когда вы ожидаете ввода-вывода). Существует третья распространенная модель параллелизма: процессы. Вы можете использовать сервер preforking или запустить несколько процессов самостоятельно. Хотя на первый взгляд это кажется плохой идеей, у нее есть некоторые преимущества: в обычной реализации Ruby это единственный способ одновременного использования всех ваших процессоров. И вы избегаете общего состояния, поэтому нет расы по определению. Кроме того, многопроцессорные приложения легко масштабируются на нескольких машинах. Помните, что вы можете комбинировать несколько процессов с другими моделями параллелизма (четными, кооперативными, упреждающими). ​​

Выбор в основном делается на используемом вами сервере и промежуточном программном обеспечении:

  • Мультипроцесс, без предварительной обработки: Mongrel, Thin, WEBrick, Zbatery
  • Мультипроцесс, предварительная обработка: Единорог, Радуга, Пассажир
  • Evented (подходит для синатра-синхронии): Тонкий, Радуга, Збатери
  • Резьбовые: Net :: HTTP :: Server, Резьбовые монгрелы, Puma, Rainbows, Zbatery, Thin [1], Phusion Passenger Enterprise> = 4

[1] начиная с Sinatra 1.3.0, Thin будет запускаться в многопоточном режиме, если он запускается с помощью Sinatra (то есть с ruby app.rb, но не с командой thin или с rackup).

6 голосов
/ 08 июня 2011

Пока гуглил, нашел этот драгоценный камень:

sinatra-synchrony

, который может помочь вам, потому что это касается вашего вопроса.

Тамтакже является эталоном, они сделали почти то же самое, что и вы (внешние вызовы).

Вывод: EventMachine - вот ответ!

4 голосов
/ 04 мая 2013

Думаю, я мог бы разработать для людей, которые сталкиваются с этим.Sinatra включает в себя этот небольшой кусок кода:

   server.threaded = settings.threaded if server.respond_to? :threaded=    

Sinatra определит, какой гем вы установили для веб-сервера (он же, thin, puma и т.быть резьбовым, если требуется.Ухоженная.

1 голос
/ 11 сентября 2011

В последнее время я сам добираюсь до JRuby и очень удивляюсь, насколько просто переключиться с MRI на JRuby.Это в значительной степени предполагает обмен нескольких драгоценных камней (в большинстве случаев).

Вам следует взглянуть на комбинацию JRuby и Тринидад (сервер приложений).Torquebox также представляет собой интересное решение «все в одном», которое включает в себя гораздо больше, чем просто сервер приложений.

Если вы хотите иметь сервер приложений, поддерживающий многопоточность, и вы знакомы сMongrel, Thin, Unicorn и т. Д., Тогда Trinidad, вероятно, легче всего перенести, поскольку он практически идентичен с точки зрения пользователей.Люблю это до сих пор!

1 голос
/ 23 июня 2011

После внесения некоторых изменений в код я смог запустить приложение padrino / sinatra на mizuno , Сначала я пытался запустить приложение Padrino на jRuby, но оно было просто слишком нестабильным, и я не стал выяснять, почему. Я столкнулся с сбоями JVM при работе на jRuby. Я также прочитал эту статью, которая заставляет меня задуматься, почему даже выбрать Ruby, если развертывание может быть совсем не простым.

Есть ли обсуждение развертывания приложений в ruby? Или я могу создать новую тему:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...