PumaとForemanを使用してゼロダウンタイムレールを設定する方法
序章
Puma は、Rackアプリ(Railsなど)を非常にうまく処理する効率的なRubyWebサーバーです。 Pumaは、スレッドおよび/またはワーカーを使用して同時実行を提供します。 Pumaのクラスターモード(ワーカーを使用)を使用して、ダウンタイムなしでアプリをデプロイできます。 プーマは労働者を一人ずつ再開し、他の労働者はこの間も処理を続けます。 これは、アプリに更新をデプロイするときに、応答の遅延やエラーページがユーザーに表示されなくなるため便利です。
このガイドでは、以下を使用します。
- PumaをWebサーバーとして
- Foreman がアプリを管理します(これは厳密には必要ありませんが、生活が少し楽になります)
- デプロイするCapistrano(デプロイ手順はかなり一般的であり、他の方法に簡単に再適用できます)
このガイドは、使用する既存のRailsアプリがあることを前提としています。 まだそこまで来ていない場合は、Rails入門ガイドを参照してください。 このガイドでは、Ubuntuを使用していることも前提としています。 設定方法については、こちらをご覧ください。 このガイドでは、Upstartを使用します。
Pumaのインストール
PumaはRubyGemsからインストールできます。
gem install puma
インストールすると、次の電話をかけるだけでPumaを使用してアプリを起動できます。
puma config.ru # or whatever your *.ru file is called
ただし、代わりに、Foremanを使用してアプリを管理します。 読む。
フォアマンのインストール
Foremanは、RubyGemsを使用してインストールできます。
gem install foreman
PumaとForemanを使用したレールの構成
まず、Gemfile
にプーマとフォアマンを追加します。
# Gemfile
gem 'puma'
gem 'foreman'
そしてインストール:
bundle install
Foremanには、実行するプロセスを指定するために使用されるProcfile
が必要です。 プロセスにweb
やworker
などの名前を付けることができます。これらの名前を使用して、実行するプロセスのタイプを区別できます。 次に行うことは、Procfile
を作成することです。
echo "web: bundle exec puma -e $RAILS_ENV -p 5000 -S ~/puma -C config/puma.rb" >> Procfile
ポート番号は好きなように変更できます。5000を使用します。 次に、puma構成ファイルを作成し、次のように編集します。
# config/puma.rb
threads 1, 6
workers 2
on_worker_boot do
require "active_record"
cwd = File.dirname(__FILE__)+"/.."
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"] || YAML.load_file("#{cwd}/config/database.yml")[ENV["RAILS_ENV"]])
end
スレッドとワーカーの数を正しく構成することが重要です。PumaREADMEは、これを行うための最善の方法に関するアドバイスを提供します。 Pumaをクラスターモードで実行するには、少なくとも2人のワーカーが必要です。 通常、VPSで使用可能なコアの数と一致させる必要があります。 Ubuntuでは、次のコマンドを使用できます。
grep -c processor /proc/cpuinfo
コアの数を確認します。 または、使用している液滴の種類に基づいて判断することもできます。 また、各ワーカーは指定された数のスレッドを使用するため、上記の構成では、最小で2つ、最大で12のスレッドが存在することに注意してください。
on_worker_boot
ブロックは、ワーカーが起動されるたびにActiveRecord接続を確立します(つまり、 デプロイ中)。 別のORMを使用している場合は、ここで適切な接続を行う必要があります。
Procfile
とpuma.rb
を構成すると、アプリケーションを実行できるようになります。 これを行うには、次のコマンドを実行するだけです。
foreman start
ロードされると、アプリはlocalhost:5000(またはProcfile
で指定したポート)で利用できるようになります。
展開
Foremanは、他のプロセス管理フォーマットにエクスポートできます。 UbuntuプロセスマネージャーであるUpstartを使用します。 Foremanを使用して、次のコマンドを実行することにより、Ubstart互換のスクリプトをエクスポートできます。
sudo foreman export upstart /etc/init -a puma-test-app -u puma-test-user -l /var/puma-test-app/log
この例では、puma-test-app
とpuma-test-user
は、適切なアプリ名とシステムユーザーに置き換えられます。 ただし、これをローカルで実行する必要はありません。デプロイの一部としてupstartスクリプトを自動的に作成することで、アプリを常に正しく起動し、Upstartで実行を継続できるようにします。
Capistranoを使用してデプロイします。 まだ行っていない場合は、次のコマンドを実行して、Capistranoで動作するようにアプリを設定します。
capify .
アプリのルートディレクトリにあります。 次に、config/deploy.rb
で作成したファイルに、以下を追加します。
# config/deploy.rb
set :app_name, "puma-test-app"
set :user, "puma-test-user"
namespace :foreman do
desc "Export the Procfile to Ubuntu's upstart scripts"
task :export, :roles => :app do
run "cd #{current_path} && #{sudo} foreman export upstart /etc/init -a #{app_name} -u #{user} -l /var/#{app_name}/log"
end
desc "Start the application services"
task :start, :roles => :app do
run "#{sudo} service #{app_name} start"
end
desc "Stop the application services"
task :stop, :roles => :app do
run "#{sudo} service #{app_name} stop"
end
desc "Restart the application services"
task :restart, :roles => :app do
run "#{sudo} service #{app_name} start || #{sudo} service #{app_name} restart"
end
end
foreman:export
タスクはUbuntuのUpstartスクリプトを更新します。これは、デプロイするたびに呼び出されます。 他のタスクは、Upstartがサポートするサービスを管理します。 Procfile
は定期的に変更されませんが、変更された場合は、アプリケーションサービスを再起動して、これらの変更を登録する必要があります。 これを実行するには、次を実行します。
cap foreman:restart
ただし、ほとんどの場合、私たちがやりたいのは、段階的な再起動を行うようにPumaに指示することだけです。 これを行うには、Capistrano deploy:restart
タスクを使用します。このタスクは、標準のCapistranoデプロイメントの一部として自動的に実行されます。 config/deploy.rb
に以下を追加します。
namespace :deploy do
task :restart, :roles => :app do
foreman.export
# on OS X the equivalent pid-finding command is `ps | grep '/puma' | head -n 1 | awk {'print $1'}`
run "(kill -s SIGUSR1 $(ps -C ruby -F | grep '/puma' | awk {'print $2'})) || #{sudo} service #{app_name} restart"
# foreman.restart # uncomment this (and comment line above) if we need to read changes to the procfile
end
end
deploy:restart
タスクが最初に行うことは、foreman:export
を呼び出してUpstartスクリプトを更新することです。 次に、SIGUSR1
シグナルを実行中のすべてのPumaインスタンスに送信します。 これは、PumaマスタープロセスのプロセスIDを見つけて、適切なシグナルを送信することによって行われます。 コメントアウトされたコマンドはOSXでPIDを検出します。ローカルでテストする必要がある場合に備えて、両方を手元に置いておくと便利な場合があります。 PumaがSIGUSR1
信号を受信すると、段階的な再起動を開始します。 なんらかの理由でSIGUSR1
信号を送信できない場合は、従来の方法でサービスを再開することにフォールバックします。
Procfile
への変更を登録する必要がある場合は、foreman:restart
タスクを呼び出す必要があります。 これには、run
で始まる行をコメントアウトし、foreman.restart
行のコメントを解除します。 理想的にはProcfile
は展開間で同じままであるため、これを定期的に行う必要はありません。
テスト
テストする前に、上記の手順を使用してForemanがUbuntuVPSにインストールされていることを確認してください。
まだ行っていない場合は、Capistranoで動作するようにVPSを設定する必要があります。 まず、Webサーバーやリポジトリなどのconfig.deploy.rb
に空欄を埋めます。 次に、以下を実行してVPSを構成します。
cap deploy:setup
その後、次を実行できます。
cap deploy
最初の展開を行います。 このデプロイ中に、アプリはVPS上のUbuntuサービスとして開始されます。 以降のすべての展開では、PumaにSIGUSR1
信号が送信され、段階的な再起動がトリガーされます。 再起動プロセス全体を通してアプリを使い続けることができるはずです。
データベースの移行
Pumaが段階的な再起動を実行している間、アプリは2つの異なるコードベースを実行します。 したがって、両方のコードベースが既存のデータベーススキーマで機能することを確認する必要があります。これは、移行を行う必要がある場合は注意が必要な場合があります。 (大幅な移行が必要で、サイトをオフラインにする必要がある場合は、新しいforeman:stop
Capistranoタスクを呼び出してから、foreman:start
タスクを呼び出して後でオンラインに戻すことができます。 )。