2015-04-24 3 views
2

У меня есть простое приложение, и я хочу использовать его как webservice.WebService Concurrency on Rails

Моя проблема заключается в том, что я не могу получить более одного запроса одновременно.

По-видимому, запросы обнуляются и выполняются один за другим. Итак, если я делаю 2 запроса по одному и тому же URL-адресу, второй должен дождаться первого.

Я уже пытался использовать Unicorn, Puma и Thin для включения параллелизма в запросах, но, похоже, он ставит в очередь запросы по URL-адресу.

Пример:

  • я сделать запрос 1 на локальном хосте: 3000/пример
  • я сделать еще один запрос на локальном хосте: 3000/another_example
  • я сделать последний запрос на локальном хосте: 3000/пример

Первый и второй запросы выполняются одновременно, но последний (имеющий тот же URL-адрес, что первый) должен ждать f или первый, чтобы закончить.

Единорог, Puma и Thin позволяют параллелизм, но по разным URL-адресам.

ПРИМЕЧАНИЯ:

Я добавил на моем config/application.rb:

config.allow_concurrency = true 

Я бегу приложение с:

rails s Puma 

Как я могу выполнять мои запросы одновременно?

ответ

1

Вы правы, каждый рабочий из Puma/Thin/Unicorn/Passenger/Webrick содержит один экземпляр приложения Rails (или экземпляр приложения Sinatra и т. Д.) Для каждого процесса Ruby. Таким образом, это 1 веб-работник = 1 экземпляр приложения = 1 процесс Ruby.

Каждый запрос блокирует процесс до тех пор, пока ответ не будет готов. Таким образом, это обычно 1 запрос за процесс.

Ruby сам имеет так называемый «GIL» (Global Interpreter Lock), который блокирует выполнение нескольких потоков из-за недостатков C-расширений, связанных с потоками, таких как мьютексы и семафоры. Это означает, что потоки не будут запускаться одновременно. На практике они «могут». Операции ввода-вывода могут блокировать выполнение, ожидая ответа. Например, чтение файла или ответ ожидания от сетевого сокета. В этом случае Ruby разрешает возобновление другого потока до завершения операции ввода-вывода предыдущего потока.

Но у Rails всегда был один блок исполнения по запросу, это собственный замок. Но в Rails 3 они добавили потокобезопасные элементы управления через код Rails, чтобы убедиться, что он может работать в JRuby, например. И в Rails 4 они решили использовать поточно-безопасные элементы управления по умолчанию.

Теоретически это означает, что более одного запроса может выполняться параллельно даже в Ruby MRI (поскольку он поддерживает родные потоки начиная с версии 1.9). На практике один запрос может выполняться, в то время как другой ожидает, что процесс базы данных вернется, например. Поэтому вы должны увидеть несколько запросов, выполняемых параллельно.Если ваш пример связан с ЦП (более внутренняя обработка, чем блоки ввода/вывода), эффект должен быть таким, как если бы запросы выполнялись один за другим. Теперь, если у вас больше блоков ввода-вывода (как ожидающих возврата большого SQL-запроса), вы должны увидеть, что он работает больше параллельно (хотя и не полностью).

Вы будете чаще видеть параллельные запросы, если используете виртуальную машину с не только собственными потоками, но и глобальную блокировку интерпретатора, например, JRuby. Поэтому я рекомендую использовать JRuby с Puma.

Puma и пассажирский многопоточный. Единорог основан на fork. Тонкий - это Eventmachine. Я лично рекомендовал бы проверить Пассажира.

+0

Passenger Enterprise/Pro является многопоточной. Тем не менее, Passenger Open Source является только процессом с несколькими процессами. Это большая разница в отношении управления ресурсами ОС в каждой версии при использовании нескольких сотрудников. – barbolo