systemdのサービスでdelayed_jobの起動と監視を行ってみた


systemdとは

Systemdとは、Linuxの起動処理やシステム管理を行う仕組みです。CentOS7以前は /etc/init.d 以下にシェルスクリプトを置いてOS起動時にサービスの自動起動を行っていましたが、CentOS7からはsystemdは *.service ファイルを記述しUnitという単位で管理するようになりました。
この仕組を利用すればサービスの自動起動だけでなく、プロセスの監視を行い停止したら再起動を行うこともできます。

delayed_jobとは

古くからRailsで利用されているバックグラウンド処理を行うための仕組みです。delayed_job_active_record.gem を利用します。

delayed_jobの問題点

delayed_jobはDBにバックグラウンド処理を行うためのキュー情報を保存するため、RDBMSの再起動等で接続が切断してしまうと、サービス自体が停止してしまいます。そのため、以前は monit 等を利用してプロセスを監視し、停止している場合は再起動を行う必要がありました。
ここでは、systemdを利用してプロセスの監視を行ってみます。

delayed_job起動スクリプト

/opt/project/bin 以下にdelayed_jobの起動スクリプトを置きます。 project の部分はご自分の環境に合わせて書き換えて下さい。

delayed_job.sh

Capistrano のdelayed_jobプラグインが実行するコマンドを真似て次のように記述しました。パス等はご自分の環境に合わせて書き換えて下さい。

#! /bin/sh
sudo su -l kazuhisa -c "cd /home/kazuhisa/apps/project/current && RAILS_ENV=production /home/kazuhisa/.rbenv/bin/rbenv exec bundle exec bin/delayed_job -n 1 start"

実行権限を与えます。

# chmod 755 delayed_job.sh

serviceファイル

/etc/systemd/system 以下にserviceファイルを置きます。

delayed_job.service

注意点は次の通り

  • ConditionPathExists に起動スクリプトを置いたパスを設定します。
  • ExecStart に起動スクリプトをフルパスで設定します。
  • Restartは on-failure を指定します。よく always を指定している例があるのですがCapistranoでデプロイ時にdelayed_jobがリスタートしたタイミングで、死活監視が動作してしまい、無駄に再起動が実行されてしまいます。 on-failureを指定することで異常終了したときだけサービスを再起動することができます。
  • RestartSecはプロセスの停止を検知してから起動するまでの時間を秒で指定します。
  • PIDFile はdelayed_job実行時のpidファイルの場所を設定します。
[Unit]
Description = start delayed_job
After=local-fs.target
ConditionPathExists=/opt/project/bin

[Service]
ExecStart=/opt/project/bin/delayed_job.sh
Restart=on-failure
RestartSec=30
Type=forking
User=kazuhisa
Group=kazuhisa
PIDFile=/home/kazuhisa/apps/project/current/tmp/pids/delayed_job.pid

[Install]
WantedBy=multi-user.target

サービスの有効化

# systemctl daemon-reload
# systemctl enable delayed_job.service
# systemctl start delayed_job.service

delayed_jobの再起動の確認

プロセスを強制的に停止してみます。しばらく待つと再起動することが確認できると思います。

$ cat tmp/pids/delayed_job.pid
17449
$ kill -9 17449
(しばらく待つ)
$ cat tmp/pids/delayed_job.pid
20409
$ ps ax | grep 20409
20409 ?        Sl     0:00 delayed_job
20419 pts/1    S+     0:00 grep --color=auto 20409

これで安心してdelayed_jobを使うことができますね。

参考