スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Tag:スポンサー広告 

【Ruby】Railsで重たい処理をバックグラウンドで非同期に処理させるResqueを使ってみた

こんばんは。最近食べ過ぎ生活がたたって2kgの体重増加を果たしてしまいました。

今回のエントリではRailsである処理を非同期に処理させるためのgem、Resqueを使ってみたのでメモします。

簡単に言うと、リクエストを受けて、レスポンスを返すまでの間で、時間のかかる重たい処理をとりあえず「あとで」処理させるということをやります。

こうすることですぐに処理結果を返さなくていい処理を後で実行して、レスポンスをすぐに返すことが可能になります。

例えば、予約を受け付けて、確認のメールを送る処理などで使えそうですね。

今回はさらに一歩踏み込んで、この「あとで」処理する部分のプロセスをデーモン化してみます。

インストール&準備


Redisサーバの準備

ダウンロード
wget 'http://redis.googlecode.com/files/redis-2.2.13.tar.gz'

コンパイル
tar xvfz redis-2.2.13.tar.gz
cd redis-2.2.13
make

redisサーバの起動
cd redis-2.2.13
src/redis-server

Railsにresqueとdaemon-spawnを組み込む

•Gemfile

gem 'resque'
gem 'daemon-spawn', :require => 'daemon_spawn'

を追記
bundle installも忘れずに

•taskファイルの追加
vim lib/tasks/resque.rake

require 'resque/tasks'


実際の処理


initializersの用意

vim config/initializers/load_resque.rb


require 'resque'

if Rails.env.to_s == "production"
Resque.redis = 'production_server:6379'
elsif Rails.env.to_s == "test"
Resque.redis = 'test_server:6379'
else
Resque.redis = 'development_server:6379'
end

ここでは各動作モードによってサーバを振り分けています。

デーモンスクリプトの用意

非同期処理を行ってくれるプロセスをデーモン化するスクリプトを用意します。

vim script/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('default')
@worker.verbose = true
@worker.work
end

def stop
@worker.try(:shutdown)
end
end

ResqueWorkerDaemon.spawn!({
: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
})


このデーモンスクリプトの起動、停止などは

script/resque_worker [start|stop|restart]

のようにして起動、停止、再起動ができます。便利です。
ただし気をつけなければいけないのはRailsのクラスなどをすべて読み込むのでアプリケーションのソースなどに変更を入れた場合、再起動して読み込み直さなければいけません。

非同期で行う処理

実際に非同期で行う処理になります。

vim app/worker/worker_test_worker.rb

class WorkerTestWorker
@queue = :default

def self.perform(user)
#メールを送る処理などを記述
end
end


非同期処理を発行する

コントローラなどから非同期処理を発行する処理です。

vim app/controllers/worker_test_controller.rb

class WorkerTestController
def create
user = User.new
#(処理)
user.save
Resque.enqueue( WorkerTestWorker, user)
#(処理)
end
end


※workerにコントローラから引数を渡す場合(今回の例ではActiveRecordのオブジェクトuser)引数はすべてworkerで受け取るときにハッシュに変換されているのでハマらないように。僕はすこしハマりました。

デプロイ


僕は普段capistranoを利用しています。
先ほども少し触れましたが、デーモンとして動くワーカープロセスはRailsアプリケーションのクラスなどを読み込みます。当然デプロイしたあともこのプロセスを再起動して、クラスなどを読み込み直さないといけません。
細かいところは割愛しますが、大体以下のようにやるとうまくdeployの時にもworkerを再起動できます。


namespace :deploy do
set :resque_worker, "RAILS_ENV=production /(Railsアプリケーションのpath)/current/script/resque_worker"

task :start do
run "#{resque_worker} start;"
end

task :stop do
run "#{resque_worker} stop;"
end

task :restart do
run "#{resque_worker} restart;"
end
end


おわりに


以上でresqueとdaemon-spawnをつかった非同期処理の紹介になります。
非同期処理を積極的に利用することで、ユーザに待たせる時間をかなり短縮できます。
少しタイムラグを許容できる重たい処理はぜひ非同期処理することをおすすめします。
スポンサーサイト
テーマ : プログラミング
ジャンル : コンピュータ

Tag:Ruby  Trackback:0 comment:0 

Comment

comment form
(編集・削除用):
管理者にだけ表示を許可
プロフィール

6rats

Author:6rats
こんにちは、ITベンチャーで働くエンジニアです
主に自分の周りで起きた技術的なことをメモとして書き残して行きます。
Android以外にもRuby/Ruby on RailsやFuelPHPなどなどたまにやります。基本的なスタンスとしては興味があるもしくは必要になったらいろんなことにチャレンジします。
最近はiOSアプリ開発を始めています。

購読
follow us in feedly
個人プロダクト

Androidアプリ

Twitterクライアント

Webアプリケーション

EcPriceWatch(Amazon価格の推移を計測、最安値を知らせるサービス)
Google AdSense
ブログ村
にほんブログ村 IT技術ブログへ
にほんブログ村
ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。