У Rails есть много решений для фоновых заданий. Одним из них является блестящий Gem под названием Sidekiq, о котором мы писали ранее на Sitepoint .
Sidekiq великолепен и может удовлетворить большинство потребностей разработчиков. Это особенно полезно, так как берет на себя тяжелый подъем от Rails. Тем не менее, у него есть несколько недостатков:
- Если вы не являетесь профессиональным пользователем (750 долларов в год), и ваш процесс падает, вы потеряете работу.
- Если ваша рабочая нагрузка увеличивается, вам потребуется более мощная версия Redis, которая стоит больше денег и ресурсов.
- Вам необходимо разместить его панель мониторинга, чтобы отслеживать, что происходит с вашей работой.
Другим подходом, который вы можете рассмотреть для обработки заданий в очереди, является Shoryuken , который работает в сочетании с Amazon SQS (Simple Queue Service). Это базовое хранилище сообщений, которое вы можете обработать позже с помощью работников Shoryuken. Эти рабочие затем работают вне основных процессов Rails. С помощью SQS и Shoryuken вы создаете очередь для использования вашими работниками, и эти работники циклически выполняют задания, пока очередь не опустеет.
Несколько преимуществ использования Shoryuken:
- Он построен с учетом Amazon SQS, что невероятно дешево ($ 0,50 за 1 миллион запросов Amazon SQS).
- SQS построен в масштабе. Вы пользуетесь преимуществами удивительной инфраструктуры Amazon, поэтому ваших сотрудников легко масштабировать.
- Amazon предоставляет простую консоль для просмотра ваших очередей, а также для настройки того, что происходит с мертвыми сообщениями.
- Ruby SDK от Amazon очень гибок в создании очередей. Вы можете создать столько, сколько хотите.
В этой статье я расскажу вам, как настроить Shoryuken для использования с Flickr API. Вы увидите, как Шорюкен обрабатывает задания в фоновом режиме со скоростью освещения.
Чтобы начать этот урок, мы собираемся использовать API Flickr, чтобы создать простую панель поиска, где мы можем генерировать фотографии на основе любого введенного идентификатора.
- Прежде всего, нам нужно настроить учетную запись Yahoo , так как это единственный способ получить доступ к Flickr API. Если у нас есть аккаунт Yahoo, просто зайдите на страницу Flickr Docs
- Нажмите на ссылку « Создать приложение» на странице документов Flickr .
- Подать заявку на некоммерческий ключ на Flickr.com .
- На следующей странице вам будет предложено ввести некоторые сведения о вашем проекте. Просто введите имя и другие сведения о вашем проекте.
- Вы получите ключ и секрет для своего заявления. Запишите их куда-нибудь, потому что они понадобятся нам для этого урока.
Затем настройте приложение Rails с помощью одного действия контроллера. Чтобы настроить новое приложение Rails, сгенерируйте его из командной строки:
rails new shoryuken_flickr
Далее настройте контроллер. Стандартное действие контроллера с index
rails g controller Search index
Добавьте корневой маршрут к этому действию в config / rout.rb :
root 'search#index'
На странице указателя настройте простую форму поиска:
<%= form_tag("/", method: "get") do %>
<%= text_field_tag(:flickr_id) %>
<%= submit_tag("Search") %>
<% end %>
Мы должны настроить модуль Flickr для возврата фотографий отправляемого идентификатора пользователя:
- Сначала мы устанавливаем flickr_fu, который позволяет легко получать нужные данные.
-
Настройте файл flickr.yml с нашими соответствующими учетными данными. Этот файл находится в папке config и выглядит так:
key: <%= ENV["flickrkey"] %> secret: <%= ENV["flickrsecret"] %> token_cache: "token_cache.yml
- Теперь мы создаем вспомогательный метод для возврата фотографий для страницы индекса. В app / helpers / search_helper.rb добавьте следующее:
module SearchHelper def user_photos(user_id, photo_count = 5) flickr = Flickr.new(File.join(Rails.root, 'config','flickr.yml')) flickr.photos.search(:user_id => user_id).values_at(0..(photo_count - 1)) end end
Этот метод возвращает фотографии на основе предоставленного идентификатора пользователя Flickr. В app / controllers / search_controller.rb нам нужно ввести действие, чтобы получить эти данные:
class SearchController < ApplicationController
def index
if params[:flickr_id]
@photos = user_photos(params[:flickr_id],10).in_groups_of(2)
@id = params[:flickr_id]
end
end
end
Теперь просто создайте небольшой фрагмент для создания фотографий. В app / views / search добавьте файл photos.html.erb со следующим:
<ul>
<% @photos.each do |photo| %>
<li> <% photo.each do |p| %>
<%= link_to(image_tag(p.url(:square), :title => p.title, :border => 0, :size => '375x375'), p.url_photopage) %>
</li>
<% end %>
<% end %>
</ul>
Идентификаторы Flickr присутствуют в профилях пользователей в URL. Пример ID: 138578671@N04
Теперь у нас есть работающее приложение, которое получает новые фотографии с Flickr. Это потрясающе, но очень медленно для пользователя и каждый раз обновляет всю страницу.
Я думаю, что это приложение будет лучше с небольшим количеством AJAX. Во-первых, создайте представление index.js.erb в app / views / search и вставьте в него простой Javascript:
$('ul').remove();
$('#flickr').append("<%= j render 'photos'%>").html_safe();
В контроллере убедитесь, что у нас есть блок respond_to
class SearchController < ApplicationController
def index
if params[:flickr_id]
@photos = user_photos(params[:flickr_id],10).in_groups_of(2)
@id = params[:flickr_id]
end
respond_to |format|
format.html
format.js
end
end
end
Наконец, в форме поиска установите для remote
true
<br/>
<%= form_tag("/", method: "get", :remote => true) do %>
<%= text_field_tag(:flickr_id) %>
<%= submit_tag("Search") %> <% end %>
<br/>
Хорошо, это круто, но мы все еще не использовали Shoryuken. Процесс все еще однопоточный.
Настройка Шорюкена
Если у вас еще нет учетной записи Amazon Web Services (AWS) , вам необходимо ее настроить. следить
- Нажмите на раскрывающееся меню «Моя учетная запись», а затем нажмите «Консоль управления AWS».
- Войдите, и вы попадете на консоль управления AWS.
- В правом верхнем углу нажмите свое имя пользователя в строке меню, а затем нажмите «Учетные данные безопасности».
- Теперь вы попадете на страницу, где вы можете получить доступ к своим ключам доступа AWS (идентификатор ключа доступа и секретный ключ доступа)
- Нажмите «Создать новый ключ доступа» и снимите свой идентификатор ключа доступа и секретный ключ доступа. Это нужно для запуска Shoryuken и SQS.
Когда у нас есть ключи доступа AWS, следующим шагом будет установка и настройка соответствующих гемов. Сначала установите AWS SDK с соответствующими сведениями, добавив в свой Gemfile следующее:
gem 'aws-sdk', '~> 2'
Затем bundle install
Нам нужно настроить AWS SDK с соответствующими учетными данными. Я обычно создаю файл с именем aws.rb, который я помещаю в папку config / initializers
touch config/initializers/aws.rb
Добавьте следующий код в файл:
Aws.config.update({
region: "eu-west-1",
credentials: Aws::Credentials.new(your_access_key, your_secret_key)
})
sqs = Aws::SQS::Client.new(
region: "eu-west-1",
credentials: Aws::Credentials.new(your_access_key, your_secret_key)
)
sqs.create_queue({queue_name: 'default'})
Обязательно замените учетные данные вашими фактическими учетными данными.
Если мы перейдем к консоли SQS, мы увидим новую очередь, созданную, если вы перезапустите сервер Rails.
Наконец, пришло время установить камень Shoryuken. В нашем Gemfile:
gem 'shoryuken'
Создайте рабочий Shoryuken и некоторое промежуточное программное обеспечение. Я просто создаю новый каталог в приложениях, которые называются работники :
mkdir app/workers
touch app/workers/flickr_worker.rb
touch app/workers/flickr_middleware.rb
touch config/shoryuken.yml
Настройте наше промежуточное ПО Flickr:
class FlickrMiddleware
def call(worker_instance, queue, sqs_msg, body)
puts 'Before work'
yield
puts 'After work'
end
end
Настройте работника:
class MyWorker
include Shoryuken::Worker
shoryuken_options queue: QUEUE_NAME, auto_delete: true, body_parser: JSON
def perform(sqs_msg, body)
id = body.fetch('id')
flickr = Flickr.new({
key:"your_key",
secret:"your_secret",
token_cache:"token_cache.yml"
})
flickr.photos.search(:user_id => id).values_at(0..(5 - 1))
end
end
А также настройку нашего файла config / shoryuken.yml следующим образом:
aws:
access_key_id: 'AWS_KEY'
receive_message:
attribute_names:
- ApproximateReceiveCount
- SentTimestamp
region: eu-west-1
secret_access_key: 'AWS Secret Key'
concurrency: 25
delay: 0
queues:
- [default, 6]
Отлично! У нас почти все настроено и готово к работе. Осталось только отправить сообщения в нашу очередь. В поисковом контроллере введите следующее:
class SearchController < ApplicationController
include SearchHelper
def index
# 138578671@N04 submit this in the form
if params[:flickr_id]
FlickrWorker.perform_async("id" => params[:flickr_id])
sleep 0.1
@photos = Photo.find_by_user_id(params[:flickr_id]).photos
end
respond_to do |format|
format.html
format.js
end
end
end
Теперь мы просто отправляем другое сообщение. На этот раз вы должны увидеть его на консоли SQS. Возможно, вам придется обновить консоль SQS с помощью кнопки обновления, которая находится в правом верхнем углу экрана.
Вы должны увидеть сообщение в своей очереди, но по какой-то причине оно не обрабатывается. Лучше разберись с этим. Откройте другое окно терминала и перейдите к своему проекту. Когда вы там, вы должны выполнить следующую команду:
bundle exec shoryuken -R -C config/shoryuken.yml
Теперь вы должны увидеть, как ваш работник очищает очередь. Когда вы вернетесь к своему приложению, вы, вероятно, увидите ошибку. Помните, что Shoryuken работает в фоновом режиме, поэтому он не может создавать переменные экземпляра для вашего текущего процесса. Вы можете сохранить фотографии в базе данных, а затем опросить таблицу, когда результаты будут получены.
rails g model Photo user_id:string photos:string
Теперь мы просто проверим наш файл переноса и убедитесь, что добавляются правильные поля. Откройте файл миграции (в db / migrate ) и убедитесь, что он выглядит следующим образом:
class CreatePhotos < ActiveRecord::Migration
def change
create_table :photos do |t|
t.string :user_id
t.string :photos
t.timestamps null: false
end
end
end
Если все выглядит хорошо, нам нужно перенести базу данных.
rake db:migrate
Убедитесь, что сериализован массив, который возвращается в нашей базе данных. В приложении / models / photos.rb :
class Photo < ActiveRecord::Base
serialize :photos
end
Затем обновляйте нашу таблицу каждый раз, когда рабочий запускается. В нижней части SearchHelper#user_photos
photos = flickr.photos.search(:user_id => id).values_at(0..(5 - 1))
Photo.create(:user_id => id, :photos => [photos])
Чтобы увидеть, как он работает, добавьте задержку к действию контроллера поиска, чтобы дать вашей базе возможность обновиться. В реальном мире я предлагаю более элегантное решение с использованием AJAX.
sleep 1.5
Там у вас есть это. Теперь вы знаете, как использовать некоторые потрясающие библиотеки для обработки поставленных в очередь задач с помощью Shoryuken. Хотя этот пример очень надуманный, я использовал его, чтобы продемонстрировать, как использовать Shoryuken с SQS. Без сомнения, у вас, вероятно, есть хотя бы один вариант использования, который выиграл бы от сообщений в очереди.