Работа с передним или фоновым изображением в Rails (Jruby, Torquebox)

Я загружаю фотографии с помощью ajax, манипуляции и загрузка в s3 занимают много времени. Я слышал, что лучше выполнять эти задачи в фоновом режиме. Мое приложение должно подождать, пока фотографии будут загружены. Но если я выберу фоновый способ, мне нужно будет работать с веб-сокетами или повторить ajax, чтобы проверить результат (ссылки на s3) (меня это не радует). Почему очень плохо делать сложные вычисления прямо в контроллере (на переднем плане)? Сейчас я использую Torquebox(Jruby), и, насколько я понимаю, он имеет идеальный параллелизм. Означает ли это, что ожидание загрузки на s3 не потребует ресурсов и все будет работать нормально? Пожалуйста, напишите о плюсах и минусах заднего / переднего плана в моей ситуации. Спасибо!

1 ответ

Решение

Обычно считается плохой практикой блокировать обработчик веб-запросов по сетевому запросу к сторонней службе. Если этот сервис станет медленным или недоступным, это может засорить все ваши веб-процессы, независимо от того, какой ruby ​​вы используете. Это то, что вы называете "передним планом".

По сути, это поток вашей текущей настройки (на переднем плане):

  1. пользователь загружает изображение на ваш сайт, и ваш желаемый контроллер получает запрос.
  2. Ваш контроллер делает синхронный запрос на s3. Это блокирующий запрос.
  3. Ваш контроллер ждет
  4. Ваш контроллер ждет
  5. Ваш контроллер (продолжает) ждать
  6. наконец, (и это не гарантировано) вы получаете ответ от s3, и ваш код продолжает и отображает ваш заданный вид /json/text/ и т.д.

Очевидно, что шаги 3-5 являются очень плохой новостью для вашего сервера, и, как я уже говорил ранее, этот рабочий / поток / процесс (в зависимости от вашей среды сервера ruby ​​/rails) будет "задерживаться" до получения ответа от s3 (который потенциально никогда не может случиться).

Вот тот же поток с фоновым заданием с некоторой справкой javascript во внешнем интерфейсе для уведомления:

  1. пользователь загружает изображение на ваш сайт, и ваш желаемый контроллер получает запрос.
  2. Ваш контроллер создает новый поток / процесс, чтобы сделать запрос к s3. Это неблокирующий подход. Вы устанавливаете флажок на запись, которая ссылается на ваш s3-образ src, например, выполнено: false, и ваш код переходит к шагу 3. Теперь ваш новый поток / процесс будет ожидать ответа от s3, и вы установите флаг "завершено" в значение true, когда s3 ответит.
  3. Вы визуализируете ваше представление /json/text/ и так далее и освободите свой рабочий / поток / процесс для этого запроса... хорошие новости!

Теперь для забавного внешнего интерфейса:

  1. ваш клиент получает ваш ответ, вызывая ваш javascript-интерфейс для запуска повторяющейся функции, подобной setInterval, которая "пингует" ваш сервер каждые 3 секунды, где ваш внутренний контроллер проверяет, установлен ли установленный вами флаг "завершен" ранее верно, и если так, ответьте / сделайте true.
  2. Ваш клиентский javascript получает ваш ответ и либо продолжает пинговать (пока вы не назначите, что он должен сдаться), либо прекращает пинговать, потому что ваше приложение ответило true.

Я надеюсь, что это ставит вас на правильный путь. Я полагал, что написание кода для этого ответа было хуже, потому что казалось, что вы ищете плюсы и минусы. Для реальных идей реализации, я бы посмотрел на следующее:

  • Sidekiq отлично подходит для решения описанных здесь вопросов. Он будет обрабатывать создание нового процесса, где вы можете сделать запрос к s3.
  • Вот отличный Railscast, который поможет вам лучше понять код.
Другие вопросы по тегам