Rails でバッチ処理をしたい
具体的には動画のエンコードを Rails 上でやりたい。
もちろんリクエストを投げてエンコード結果のレスポンスを返すなんてことは無理だ、だからバッチでやる。Rails でバッチ処理のやり方を調べると、Rails4.2 からは ActiveJob という機能を使ってやるらしい。
冒頭に ActiveJob の目的なるものが書いてある。
>Active Job の主要な目的は、Rails アプリを即席で作成した直後でも使用できる、自前のジョブ管理インフラを持つことです。これにより、Delayed Job と Resque などのように、さまざまなジョブ実行機能の API の違いを気にせずにジョブフレームワーク機能やその他の gem を搭載することができるようになります。バックエンドでのキューイング作業では、操作方法以外のことを気にせずに済みます。さらに、ジョブ管理フレームワークを切り替える際にジョブを書き直さずに済みます。
なるほど、ジョブ管理フレームワーク(アダプタ)の差異を吸収してくれる機能なわけね。
アダプタは情報が多そうなSidekiq
を使ってみることにする。
Redis で苦しむ
Sidekiq
を使うにはRedis
のインストールが必要なようだ。WSL(Windows Subsystem for Linux)の Ubuntu で動作させる為、Redis を apt からインストールする。
sudo apt-get install -y redis-server |
うまくインストールされた。redis-server
コマンドで Redis 自体も立ち上がった。次は Sidekiq だ
Gemfile に追記し
gem 'sidekiq' |
インストールする
bundle install |
そして Sidekiq を起動……起動しない
$ bundle exec sidekiq |
redis-cli
でもダメだ
Could not connect to Redis at 127.0.0.1:6379: Connection refused |
結局原因は分からなかったが、パッケージマネージャからインストールすると Redis のバージョンが古い模様(この時 2.8 がインストールされていた)
最新バージョンをインストールする
Ubuntu Linux 14.04 LTS に Redis 3 をインストールするを参考に最新バージョンを入れる。
sudo add-apt-repository ppa:chris-lea/redis-server |
見事 4.0.9 がインストールされた…が、今度は起動しないのだ。
$ redis-server |
config ファイルの指定をしたら立ち上がった--help
には未指定ならデフォルトって書いてるのに…
sudo redis-server /etc/redis/redis.conf |
そして今度こそ Sidekiq が立ち上がった。
$ bundle exec sidekiq |
Redis を Docker で入れる
ここまでやって「あれ…Docker でいいんじゃね?」と気付く
docker run --name redis -d -p 6379:6379 redis redis-server |
らくちーん!
Sidekiq で苦しむ
ActiveJob の動作テストをする為に、まず Job を作成する。
$ bundle exec rails g job encoder |
Job にはログ出力のみ追記しておく。
class EncoderJob < ApplicationJob |
そしてrails runner
で ActiveJob をキックする。
bundle exec rails runner 'EncoderJob.perform_later' |
…ログが出ない
[ActiveJob] Enqueued Encoder::Job (Job ID: 2f2f8b9e-ce21-474b-b8d7-152aac0750f2) to Sidekiq(encoder) |
Enqueue と Perform のログは出ているので実行はされているようだが、肝心のRails.logger.debug('do job!')
が出力されない。
解決… Rails でバッチ処理を作成してみる(runner の場合) rails runner
でキックする場合Logger
をnew
しないとダメなんかい
queue でさらに詰まる
queue_as :default
をqueue_as :encoder
に変えたらまたログが出なくなった。
起動時に使用するキューの設定を-q
でする必要があった bundle exec sidekiq -q default encoder
で OK…ではない-q
直後のキューしか認識しない-q default
なら default しか動かないし、-q encoder
なら encoder しか動かない sidekiq.yml
で設定したら両方動いた、なんでだろ…
:verbose: false |
bundle exec sidekiq -C config/sidekiq.yml |
これで OK
ダッシュボードはいい
Sidekiq にはダッシュボードがついている、これはいいものだ、以下の設定で有効になる。
# config/routes.rb |
開発環境ならhttp://localhost:3000/sidekiq
にアクセスで表示される。
アダプタ意識しなくていい?
冒頭で ActiveJob はジョブ管理フレームワーク(アダプタ)の差異を吸収すると書いたが、結局 Sidekiq がっつり覚えなきゃ最低限の動作も難しかった。
アダプタを変更しても ActiveJob より先は修正が必要ないという事だろうけど、アダプタの変更ってそんな発生するものだろうか?ActiveJob のメリットが感じ辛かった、Sidekiq 単体でいいんじゃないかと。
全くの 0 から導入する場合、ActiveJob+Sidekiq+Redis
とSidekiq+Redis
なら明らかに後者の負荷が低いだろう。