Действительно ли контроллеры направляющих являются многопоточными? Thread.exclusive в контроллерах

Так же, как матовый сказанный b вопрос не очень ясен. Предположение, что Вы спрашиваете о поддержке многопоточности на языке: потому что это не необходимо для 99,999% приложений, работающих в браузере в настоящее время. При реальной необходимости в нем существуют обходные решения (как использование window.setTimeout).

В общей многопоточности очень, очень, очень, очень, очень, очень трудно (я говорил, что это твердо?) для разбираний, если Вы не вставляете дополнительные ограничения (как использование только неизменных данных).

7
задан Dan Rosenstark 7 September 2009 в 11:48
поделиться

3 ответа

Запуск промежуточного программного обеспечения rake в базовом приложении rails дает следующее:

use Rack::Lock
use ActionController::Failsafe
use ActionController::Reloader
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActiveRecord::SessionStore, #<Proc:0x017fb394@(eval):8>
use ActionController::RewindableInput
use ActionController::ParamsParser
use Rack::MethodOverride
use Rack::Head
run ActionController::Dispatcher.new

Первый элемент в стеке стойки - Rack :: Lock . Это накладывает блокировку на каждый запрос, поэтому одновременно обрабатывается только один запрос. Таким образом, стандартное приложение rails является однопоточным. Однако вы можете создавать новые потоки в запросе, который сделает ваше приложение многопоточным, большинство людей никогда с этим не сталкивается.

Если у вас возникают проблемы…

require 'thread'
Thread.exclusive do
     # stuff here
end

… это гарантирует, что содержимое внутри блока никогда не будет выполняться параллельно с любой другой код. Создание общего мьютекста между всеми потоками (в переменной класса или что-то в этом роде, но его можно стереть при перезагрузке в режиме разработки, поэтому будьте осторожны) и заблокируйте его как Rack :: Вызов Lock # должен быть предпочтительным, если вы просто хотите, чтобы два экземпляра одного и того же кода не выполнялись одновременно.

Кроме того, для записи каждый запрос создает и разыменовывает один контроллер в каждом запросе цикл. Никакие два запроса не должны видеть один и тот же экземпляр, хотя они могут видеть один и тот же класс.

Установка config.threadsafe! аннулирует почти все, что я сказал. Это удаляет Rack :: Lock из стека, и означает, что вам нужно будет установить мьютекс вручную, чтобы предотвратить двойной ввод. Не делайте этого, если у вас нет действительно веской причины.

Даже без Rack :: Lock вы все равно получите один экземпляр контроллера на запрос. Точка входа в ваш контроллер гарантирует, что заметит вызов new в процессе .

13
ответ дан 6 December 2019 в 14:06
поделиться

Ruby является однопоточным. Таким образом, в любое время контроллер может обрабатывать только один запрос за раз. Если запросов больше одного, они ставятся в очередь. Чтобы избежать этого, люди обычно запускают небольшой набор Mongrels, чтобы добиться хорошего параллелизма. Это работает следующим образом (прямо из Mongrel WIKI FAQ ):

  1. Запрос попадает в mongrel.
  2. Mongrel создает поток и анализирует заголовки HTTP-запроса
  3. Если тело маленькое, то оно помещает тело в StringIO
  4. Если тело большое, оно передает тело во временный файл
  5. Когда запрос "готовится", он вызывает RailsHandler.
  6. RailsHandler видит, возможно ли, что файл является страницей. cached, если да, то он отправляет кешированную страницу.
  7. Теперь вы наконец готовы обработать запрос Rails. LOCK!
  8. По-прежнему заблокировано, Mongrel вызывает Rails Dispatcher для обработки запроса, передавая заголовки и StringIO или Tempfile для тела.
  9. Когда Rails завершает работу, РАЗБЛОКИРУЙТЕ! . Rails (надеюсь) поместил весь свой вывод в StringIO.
  10. Затем Mongrel берет этот вывод StringIO, любые заголовки вывода и очень быстро передает их обратно клиенту.

    Обратите внимание на то, что если страница кэшируется, блокировки нет.

1
ответ дан 6 December 2019 в 14:06
поделиться

Насколько я понимаю, новый экземпляр контроллера создается для каждого HTTP-запроса, обрабатываемого контроллером.

1
ответ дан 6 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: