Rails 6(Puma)をsystemdの再起動に対応させる(Hot restart)
はじめに
Rails 5でPumaが標準のアプリケーションサーバーになりましたが、UnicornのままだったRails 6アプリをようやくPumaに変更したので公式で紹介されているsystemdで動かすようにしました。
このままではrestart
のみでnginxのようなreload
に対応していないため、シャットダウン->起動となりサービスが瞬断されます。nginxのようにreload
に対応させて再読み込みしつつシャットダウンなしの再起動に対応します。具体的にはExecReload
を追加します。
環境はRails 6.1.7.3、Puma 5.6.5をAWS EC2のAmazon Linux2で動かしています。
設定ファイルの作成と必要なgemの追加
puma.service
/etc/systemd/system
に設定ファイルを作成します。
[Unit]
Description=Puma HTTP Server
After=network.target
[Service]
Type=notify
# 公式の10秒では再起動中にwatchdogによってプロセスがkillされたので長めに
WatchdogSec=60
WorkingDirectory=<YOUR_APP_PATH>
PIDFile=<YOUR_APP_PATH>/tmp/pids/server.pid
# 必要な環境変数を指定
Environment="LANG=ja_JP.UTF-8"
Environment="RAILS_MAX_THREADS=20"
Environment="RAILS_ENV=production"
# tmp/pids/server.pidはconfig/puma.rbで指定されているもの
ExecStartPre=/usr/bin/rm -f <YOUR_APP_PATH>/tmp/pids/server.pid
ExecStart=/usr/local/rbenv/shims/bundle exec <YOUR_APP_PATH>/bin/rails server
# USR2シグナルを指定するとPumaはワーカーをリスタートします
ExecReload=/bin/kill -USR2 $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
再起動(systemctl reload puma
)に対応させているので再起動中に500エラーにならずに再起動されるはずです(rails restart
と同等なはず)。また、前段にnginxがある場合はPumaがシャットダウンされないため接続を維持します。
USR1
では設定ファイルの再読み込みがないし、USR1
を指定してもログを見ると
bundle[24680]: [24680] * phased-restart called but not available, restarting normally.
となっておりPhased restartされていなかったためUSR2
にしています。
シグナルについてはこちらを
再起動についてはこちらを
sd_notify
puma.service
でType=notify
にしているのでsd_notify
が必要です。Gemfileに追加してbundle install
します。
gem "sd_notify"
ちなみにPuma 6はsd_notify
相当のコードが組み込まれているので不要です。
systemctlで起動する
systemdに登録し、
sudo systemctl daemon-reload
Pumaを開始します。
sudo systemctl start puma
状態の確認は
sudo systemctl status puma
サービス停止は
sudo systemctl stop puma
ソケットを維持して再起動(rails restart
と同等)は
sudo systemctl reload puma
ソケットを維持せずにサービスの停止->開始での再起動は
sudo systemctl restart puma
Discussion