Pumaで動くRailsアプリで、リクエスト処理しながらサーバ再起動をする

Ruby on Rails

サーバの再起動をした時、一瞬でもサイトにアクセスできなくなると折角獲得したユーザを失うことになるかもしれません。

特にRailsのPumaでは、以外にアクセスできなくなる時間が長いです。(体感ですが5秒~10秒はアクセス不可になる)

なので、ユーザのリクエストを処理しながら再起動できるようにカスタマイズしましょう。

pumaconf.rbの編集

pumaconf.rbを編集します。私の場合は、AWS Elastic Beanstalkを使っているため、「/opt/elasticbeanstalk/support/conf/pumaconf.rb」にあります。

workers 2

とworker数を2以上にすることで、リクエストを処理しながら再起動ができるようになります。内部ではサーバが2つ起動しているような状態になり、片方が再起動している最中にもう片方でリクエストを処理するようなイメージです。

ちなみにpumaでリクエストを処理しながら再起動するためには、普通にkillしてしまうとだめなので、「sudo pkill -SIGUSR1 -f puma」のコマンドを使います。

pumaconf.rbはこんな感じになりました。

directory '/var/app/current'
threads 8, 16
workers 2
bind 'unix:///var/run/puma/my_app.sock'
pidfile '/var/run/puma/puma.pid'
stdout_redirect '/var/log/puma/puma.log', '/var/log/puma/puma.log', true
daemonize false

 

PumaWorkerKillerで更に便利に

Pumaはメモリを結構くったりします。数日動かしてたらメモリを圧迫して、メモリ90%超えのアラート通知が…

なんてことがありましたので、私は、PumaWorkerKillerというbundleを入れております。

 

Gemfileに

gem 'puma_worker_killer'

を記述して、

bundle install

を実行しましょう。その後、同様にpumaconf.rbを修正します。

私はこんなファイルにしています。メモリや再起動頻度はご自身で調整下さい。

directory '/var/app/current'
threads 8, 16
workers 2
bind 'unix:///var/run/puma/my_app.sock'
pidfile '/var/run/puma/puma.pid'
stdout_redirect '/var/log/puma/puma.log', '/var/log/puma/puma.log', true
daemonize false

before_fork do
    require 'puma_worker_killer'
    
    PumaWorkerKiller.config do |config|
        config.ram = 1024 # mb
        config.frequency = 30 # seconds
        config.percent_usage = 0.65
        config.rolling_restart_frequency = 6 * 3600 # 12時間ごとに再起動する
        config.reaper_status_logs = true # setting this to false will not log lines like:
        
        config.pre_term = -> (worker) { puts "Worker #{worker.inspect} being killed" }
    end
    
    PumaWorkerKiller.enable_rolling_restart # デフォルトは6時間だが、上で指定していれば指定した時間に再起動となる
    PumaWorkerKiller.start
end

 

コメント