search
LoginSignup
21

More than 5 years have passed since last update.

posted at

Delayed Job の導入とMackerelによる監視

本記事はクービック Advent Calendar 2015の24日目の記事です。

クービックPopcornでは、ジョブキュー として Delayed Job を導入しています。本記事では、導入から監視までの流れをご紹介します。

なお、アプリケーションは Rails 4.2 で書かれています。

事前調査

Rails4.2 から Active Job が導入されています。

Active Jobの主要な目的は、Railsアプリを即席で作成した直後でも使用できる、自前のジョブ管理インフラを持つことです。これにより、Delayed JobとResqueなどのように、さまざまなジョブ実行機能のAPIの違いを気にせずにジョブフレームワーク機能やその他のgemを搭載することができるようになります。バックエンドでのキューイング作業では、操作方法以外のことを気にせずに済みます。さらに、ジョブ管理フレームワークを切り替える際にジョブを書き直さずに済みます。

様々なジョブキューバックエンドのアダプターを Active Job が引き受けてくれるので、これを利用しない手はないです。

Active Job adapters にサポートしているキューシステムのリストがあります。このリストに独自に調べた Middleware を足した表がこちらです。

Async Queues Delayed Priorities Timeout Retries Middleware
Backburner Yes Yes Yes Yes Job Global beanstalkd
Delayed Job Yes Yes Yes Job Global Global RDBM, Redis, Mongoid, etc
Qu Yes Yes No No No Global Redis, Mongoid
Que Yes Yes Yes Job No Job PostgreSQL?
queue_classic Yes Yes No* No No No PostgreSQL
Resque Yes Yes Yes (Gem) Queue Global Yes Redis
Sidekiq Yes Yes Yes Queue No Job Redis
Sneakers Yes Yes No Queue Queue No CLOUDAMQP
Sucker Punch Yes Yes No No No No Celluloid(threads)
Active Job Inline No Yes N/A N/A N/A N/A N/A

Ruby Toolbox の Background Jobs は 以下のようになっておりました。
3a1148d26f299b376531bea5958c401c.png

ジョブキューシステムの選定基準はいろいろあろうかと思いますが、新たな Middleware の管理が不要であること、ならびに 実績が多いことを重視し、Delayed Job を採用しました。

なお、MySQL をキューに使用する 5 つの微妙な方法とその落とし穴 (翻訳版) という記事で指摘されているように、サービス規模が大きくなった場合には見直しが必要かもしれません。

導入

delayed_job を Rails なアプリケーションに導入する記事は世にたくさんあるので、やったことを軽くご紹介するに留めておきます。

Gemfile

gem 'delayed_job'
gem 'delayed_job_active_record'
gem 'daemons'

config/application.rb

config.active_job.queue_adapter = :delayed_job

config/initializers/delayed_job_config.rb

Delayed::Worker.default_queue_name = 'default'
Delayed::Worker.delay_jobs = !Rails.env.test?
Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log'))

delayed_jobs テーブルの migration を忘れずに。ここまででインストールは完了です。

次に、デーモン再起動を自動化する方法を探します。

capistrano-delayed-jobcapistrano3-delayed-job があり、「どっちがいいの?」と疑問が湧きますが、Delayed Job の wiki では後者が推奨されているので、素直に capistrano3-delayed-job を使います。

使い方は Capfile と deploy.rb に数行加えるだけ。カンタン。

Capfile

require 'capistrano/delayed-job'

config/deploy.rb

set :delayed_job_workers, 1
set :delayed_job_roles, [:app]

監視

ジョブキューシステムを導入したら、正常に稼動しているかを監視しなければなりません。

弊社では監視に Mackerel を利用していますが、Delayed Job についても チェックプラグインの仕組みを利用して監視を行っています。

/etc/mackerel-agent/mackerel-agent.conf

[plugin.checks.delayed_job]
command = "sudo -uxxxx -i bash -c 'env RAILS_ENV=production bundle exec rails runner ./bin/mackerel_plugin_checks_delayed_job'"

bin/mackerel_plugin_checks_delayed_job

10.times do
  sleep 1

  # Find pid file
  pid_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp', 'pids', 'delayed_job.pid'))

  # Read pid file
  File.open(pid_file, 'r') do |f|
    pid = f.read
  end
  next unless pid && pid =~ /\A\d+\n\z/

  # Find process
  ps = `ps #{pid}`
  next unless ps =~ /delayed_job/

  # Find failed jobs
  failed_jobs = Delayed::Job.where('last_error IS NOT NULL').where('attempts >= ?', 3)
  if failed_jobs.count > 0
    puts "failed jobs count: #{failed_jobs.count}"
    exit 2
  end

  puts "running"
  exit 0
end

puts "not running?"
exit 2

ほとんど説明不要な気もしますが、プロセスの存在監視と3回以上失敗しているジョブの監視をしています。

Go でプラグインを書くとカッコイイ気がするんですが、時間がなかったので(若干やっつけ仕事で)ruby スクリプトにしてます。

監視に引っ掛かった時は、Slack に Mackerel の bot が通知してくれます。

delayed_job_mackerel.png

まとめ

クービックPopcornにおける Delayed Job の導入〜監視をご紹介しました。

何らかの参考になれば幸いです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
21