Heroku の推奨する Ruby Web サーバーが Puma に変更になったとのアナウンスがありました。
Puma is Now the Recommended Ruby Webserver
もともと、何となく「1 Dyno で動かすなら Unicorn より Puma の方がいいんじゃないのかな?」とか思って Puma を好んでいました (ただ、ぶっちゃけロクに調べておらず、この考えはたぶん間違ってたと思う)。
が、Rails アプリが 1 つあって、その Web サーバーが Unicorn だったのでこの機会に変えました。
一応ここにその手順を書いておきますが、Deploying Rails Applications with the Puma Web Server を読んだ方がずっと良いでしょう…
Migrate from Unicorn to Puma
Heroku の推奨する構成にしたがって変更するだけならあっという間です。
Gemfile に Puma を追加する
Gemfile
に Puma を追加します。同時に、不要になる Unicorn は削除しておきます。
Gemfile
# Use Puma as the app server
gem 'puma'
$ bundle install
config/puma.rb
を作る
Puma の起動設定ファイルを作成します。以下の構成が Heroku がオススメする標準構成です。
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
ちょっとだけ中身に触れておききましょう。Puma には、Worker と Thread という、並行処理のための 2 つの単位があります。
Worker
- Puma が複数リクエストを同時に捌くために起動するプロセスのこと
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
のところ
Thread
- 起動した各 Worker の中で更に起動するスレッドのこと
- MRI では GIL (GVL) があるため IO 処理や外部への http リクエストなどでのみ有効。
threads_count = Integer(ENV['MAX_THREADS'] || 5)
のところ。
もしアプリケーションがスレッドセーフではない作りになっているのであれば、以下のようにして最大起動 Thread 数を 1 つに制限する必要があります。
$ heroku config:set MAX_THREADS=1
Procfile を変更する
上記で作った構成ファイルを読み込んで Puma が起動するように Procfile
を変更します。
Procfile
web: bundle exec puma -C config/puma.rb
config/unicorn.rb を削除
不要になった config/unicorn.rb
を削除します。
$ git rm config/unicorn.rb
Puma の起動テスト
問題なく起動するかどうか確認します。
$ env RACK_ENV=production bundle exec puma -C config/puma.rb
Heroku へのデプロイ
バッチリ起動することが確認できたら、いつものように Heroku にデプロイして完了です。
$ git add -A
$ git commit -m"Migrate web server from Unicorn to Puma"
$ git push heroku master