Как рельсы разрешают одновременные запросы?

Подготовьтесь к тесту: sleep 10 в действии

Тест: Откройте две вкладки в браузере, чтобы посетить действие

Результат: Когда выполняется второй запрос, первый запрос завершается и начинает визуализировать представление, но представление остается пустым. По завершении второго запроса оба запроса завершают показ представления одновременно.

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

Ответ 1

Используете ли вы сервер WEBrick? Это должно быть потому, что ваш сервер является однопотоковым сервером и способен выполнять один запрос за раз (из-за единственного рабочего потока). Теперь в случае нескольких запросов он запускает часть действия запроса и перед запуском средства визуализации, которое проверяет, есть ли ожидающие запросы. Теперь, если выстроились 10 запросов, сначала они будут заполнены, прежде чем будут отображаться представления. Когда все эти запросы будут завершены, представления теперь будут отображаться последовательно.

Вы можете переключиться на сервер Пассажира или Unicorn, если вы хотите многопоточную среду.

Надеюсь, что это имеет смысл.

Ответ 2

WEBrick является многопоточным, но разработчики Rails жестко закодировали мьютекс, поэтому он может обрабатывать только один запрос за раз. Вы можете обезьян-патч Rails::Server, и вы можете запускать многопоточный WEBrick.

Отметим, что WEBrick будет многопоточным только при конфигурации config.cache_classes = true и config.eager_load = true, что характерно для RAILS_ENV=production. Это связано с тем, что перезагрузка классов в разработке не является потокобезопасной.

Чтобы получить WEBrick полностью многопоточным в Rails 4.0, просто добавьте его в config/initializers/multithreaded_webrick.rb:

# Remove Rack::Lock so WEBrick can be fully multi-threaded.
require 'rails/commands/server'

class Rails::Server
  def middleware
    middlewares = []
    middlewares << [Rails::Rack::Debugger] if options[:debugger]
    middlewares << [::Rack::ContentLength]

    Hash.new middlewares
  end
end

Оскорбительный код в rails/commands/server.rb, который мы освободили, это:

# FIXME: add Rack::Lock in the case people are using webrick.
# This is to remain backwards compatible for those who are
# running webrick in production. We should consider removing this
# in development.
if server.name == 'Rack::Handler::WEBrick'
  middlewares << [::Rack::Lock]
end

Это не нужно для Rails 4.2. Это одновременно готовый вариант.

Ответ 3

в настройках конфигурации/окружения env/development.rb(или в config/application.rb)

добавить эту строку:

  #Enable threaded mode
  config.threadsafe!