Process.fork в контроллере Rails - PullRequest
4 голосов
/ 21 октября 2010

Мы делаем несколько прототипов нового приложения и заметили, что одно из действий выполнялось вечно для загрузки (80-120 секунд). Поскольку большая часть обработки не должна выполняться при загрузке страницы (мы можем запросить данные через Ajax позже), я подумал об использовании Process.fork, чтобы позволить странице немедленно вернуться, тогда как обработка все еще происходит "за кулисами" . "

Мы используем Apache с Passenger для приложения.

Пара вещей:

  1. Я знаю о delayed_jobs, resque, BJ и других фоновых заданиях. Мы используем dj, и в конечном итоге будем использовать что-то подобное и для этого. Это временное решение, пока мы создаем прототипы.

  2. Меня не интересует производительность сервера. Приложение работает на своем собственном сервере, и лишь небольшая часть пользователей его опробует.

Ранние тесты показывают, что это хорошо работает, но мне интересно, было бы неплохо использовать это. Это будет надежно? Будет ли продолжаться раздвоенный процесс, если пользователь перейдет на другую страницу или закроет вкладку / браузер? После завершения разветвления процесс завершится сам собой?

Ответы [ 3 ]

5 голосов
/ 21 октября 2010

Зависит от того, что означает «обработка». Как правило, это не будет надежным, если обработка подразумевает использование стека Rails - поскольку главный процесс, освобожденный запросом, может быть назначен другому запросу пассажиром, и вещи могут ошибаться. Также Пассажир может завершить работу главного процесса и, следовательно, экземпляра Rails в некоторых условиях (сокращение пула свободных экземпляров и т. Д.).

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

Я бы предложил использовать работников, работающих вне стека Apache / Passenger, например, используя кластеризованное BackgrounDRb или другое решение (вы упомянули Resque).

Есть еще одна идея, которую я сейчас использую для заданий cron с моим приложением. Мой crontab - это всего лишь несколько wget для действий с долго выполняющимися задачами. Вы можете сделать нечто подобное в ruby ​​fork с OpenURI по требованию. Представьте себе приложение pinging само по HTTP. Разветвленному процессу больше не нужны Rails - он просто обращается к странице задачи, и следующий Пассажир обрабатывает запрос и управляет экземпляром приложения для этого специального запроса.

В случае, если Passenger убивает родительский элемент fork и, следовательно, разветвляет процесс - другой экземпляр Rails должен продолжать обрабатывать http-запрос.

0 голосов
/ 13 февраля 2014

Просто хотел присоединиться, на случай, если Google попадет сюда.В Passenger> v4.0 есть способ сделать это, используя «Out-of-Band Work».Я использую его для длинных задач, таких как отправка электронной почты в контроллере Sinatra, например:

# Your app should tell Passenger about this OOB task, won't run otherwise
headers['X-Passenger-Request-OOB-Work'] = "true"
PhusionPassenger.on_event(:oob_work) do
  # The following line takes a while to run,
  # but won't tie up any http-serving processes
  mail.deliver!
end

Информацию можно найти здесь: http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/

Ранее я пытался использовать Process.fork и попытался убить процесс позже;в то время как это фактически выполняет первую часть, это не будет фактически убивать разветвленный процесс впоследствии, и Пассажир в конечном счете съест всю доступную память (как я кропотливо выяснил в производственной системе).Очевидно, я не могу запрограммировать, чтобы спасти мою собственную жизнь.

Надеюсь, это поможет!

0 голосов
/ 21 октября 2010

Да, это надежно, если вы используете камень, который был протестирован и использовался ранее.И DelayedJobs, и Spawn (которые я часто использую) существуют уже довольно давно и должны делать именно то, что вы ожидаете от них.

Поскольку на вашем сервере процесс выполняется в фоновом режиме, он должен продолжаться очень хорошо, если пользователь закрывает вкладку / браузер, у него нет клиентских вложений.Когда программа завершит выполнение, она сама прекратит работу и освободит память.

Вы можете прочитать больше о разветвлении на этой превосходной вики-странице .В качестве примечания не используйте метод ruby ​​fork в Rails, поскольку он не будет хорошо работать с ActiveRecord.

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