Являются ли контроллеры rails многопоточными? Нить.эксклюзив в контроллерах



Являются ли контроллеры Rails многопоточными?



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



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


On нужно ли как-то синхронизировать на мониторе?

533   3  

3 ответов:

Запуск rake middleware в приложении basic 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

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

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

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

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

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

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

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

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

Comments

    Ничего не найдено.