Hello World Resque (Railsにresqueを導入する)


Ruby2.0, Rails4で確認

resqueは非同期処理を簡単に実現してくれるgemです。

とりあえずレスポンスだけ返して実際の処理は後回しにしたい、という場合にresqueが使えます。

resqueの最新バージョンは2.x系ですが、デフォルトでインストールされるのは1.1系なので1.x系での解説をします。

1.x系の公式ドキュメントはこちらになります。

今回はresqueを使ってhello worldを出力するところまでやってみます。

resque workerのdaemon化もやってみます。

redisのインストール(mac)

resqueはredisを使用するためあらかじめredisをインストールして起動しておく必要があります。

  • brewでインストール
brew install redis
  • redis起動
redis-server

初期設定

  • アプリ作成
rails new resque_sample
  • Gemfile追加
# Gemfile

gem 'resque'
  • bundle install
./bin/bundle install --path=vendor/bundler
  • initializer設定

Workerのnamespaceを環境によって分けるように設定しておきます

# config/initializers/resque.rb

Resque.redis = 'localhost:6379'
Resque.redis.namespace = "resque:resque_sample:#{Rails.env}" # アプリ毎に異なるnamespaceを定義しておく

Controller作成

  • homeコントローラを作成
./bin/rails g controller home
  • routing設定
# config/routes.rb
get "hello/:message" => 'home#hello'
  • indexアクション編集
# app/controllers/home_controller.rb

class HomeController < ApplicationController
  def hello
    Resque.enqueue(Hello, params[:message])
    render :text => params[:message]
  end
end

ResqueWorker作成

  • resque worker用のディレクトリを作成
mkdir app/workers
  • worker作成
# app/workers/hello.rb

class Hello
  @queue = :resque_sample # Woeker起動時に指定するQUEUE名

  def self.perform(message)
    sleep 5
    logger = Logger.new(File.join(Rails.root, 'log', 'resque.log'))
    logger.info "Hello #{message}"
  end
end
  • Rakeタスクを追加
# lib/tasks/resque.rake

require 'resque/tasks'
  • worker起動

QUEUEにworker名を指定します。

QUEUE=resque_sample rake environment resque:work

# すべてのworkerを対象としたい場合は*を指定
QUEUE=* rake environment resque:work

確認

ブラウザから

にアクセスして

tail -f log/resque.log

を眺めていると数秒後にログに

Hello world
Hello resque

が記録されます。

Daemon化してみる

daemon-spawnというgemを用いることでresqueの処理をdaemon化できます。

  • Gemfile追加

requireの指定を忘れないように注意

# Gemfile

gem 'daemon-spawn', :require => 'daemon_spawn'
  • bundle install
./bin/bundle install
  • daemon起動スクリプトの作成
# bin/resque_worker

#!/usr/bin/env ruby
require File.expand_path('../../config/application', __FILE__)
Rails.application.require_environment!

class ResqueWorkerDaemon < DaemonSpawn::Base
  def start(args)
    @worker = Resque::Worker.new('resque_sample') # 複数のworkerがある場合はカンマ区切りで指定
    @worker.verbose = true
    @worker.work
  end

  def stop
  end
end

ResqueWorkerDaemon.spawn!({
  :processes => 1, # プロセス数の指定
  :working_dir => Rails.root,
  :pid_file => File.join(Rails.root, 'tmp', 'pids', 'resque_worker.pid'),
  :log_file => File.join(Rails.root, 'log', 'resque_worker.log'),
  :sync_log => true,
  :singleton => true,
  :signal => 'QUIT'
})

複数のworkerがある場合はカンマ区切りで

@worker = Resque::Worker.new('worker1', 'worker2')

と記述します。

workerに追加した順番で優先順位が決まるので上記の例だとworker1の方が優先度が高くなります。

  • 実行権限を付与
chmod 755 bin/resque_worker
  • daemon起動
RAILS_ENV=development ./bin/resque_worker start

これでworkerをdaemon化することができました。

再度ブラウザからアクセスすれば正しくログに記録されていきます。

  • その他のコマンド

停止

RAILS_ENV=development ./bin/resque_worker stop

再起動

RAILS_ENV=development ./bin/resque_worker restart

まとめ

今回はhello worldをログに残す簡単なサンプルでしたが、resqueを使用することで手軽にジョブキューシステムを導入できました。

レスポンスだけ素早く返して重い処理を後回しにしたい、という場合はresqueの検討をしてみてはいかがでしょうか。

今回のサンプルコードはこちらに置いておきます:hilotter / resque_sample

参考