Rails4.2 を Nginx + Unicorn で動作させる
概要
Rails や Padrino の案件に関わってきたが、全て Apache + Passenger の構成で動作させていた。
最近では、Nginx + Unicorn で動作させているという話しをよく聞くので、環境作りを試してみる。
前提
- Rails4.2 をインストール済み
- bundler を使っている
Unicorn のインストール
Gemfile に下記を追加。
# vim Gemfile gem 'unicorn'
下記を実行し、インストール。
# bundle install
Nginx のインストール
下記は mac で HomeBrew 使った場合。
環境によって yum なり aptitude なり使い分ける。
# brew install nginx
Unicorn の設定
config/unicorn.rb を新規作成
Unicorn の設定ファイルを必要最低限の内容で新規作成。
# vim config/unicorn.rb rails_root = File.expand_path('../../', __FILE__) rails_env = ENV['RAILS_ENV'] || "development" worker_processes 2 working_directory rails_root #listen "#{rails_root}/tmp/#{rails_env}_unicorn.sock" listen 8080 pid "#{rails_root}/tmp/#{rails_env}_unicorn.pid" stderr_path "#{rails_root}/log/#{rails_env}_unicorn_error.log" stdout_path "#{rails_root}/log/#{rails_env}_unicorn.log"
一旦、この最低限の設定で Unicorn 単体で動作してみる。
わざわざ RAILS.env の値をファイル名に利用するようにしてみた。
動かすだけなら無駄だった・・・
# bundle exec unicorn_rails -c config/unicorn.rb -E development
下記にアクセスできることや、pid ファイル、log ファイルが作成されていることを確認する。
http://localhost:8080
config/unicorn.rb を編集
Nginx と連携するために少し修正。
# vim config/unicorn.rb ... listen "#{rails_root}/tmp/#{rails_env}_unicorn.sock" #listen 8080 ...
Nginx と Unicorn の通信に Unix Domain Socket を利用してみる。
ざっくり説明すると、Nginx + Unicorn を一つのサーバ内で構築する場合、
つまり、ネットワーク越しに通信しない場合は Unix Domain Socket を利用した方が速いようだ。
詳細は下記。
nginx - 調べなきゃ寝れない!と調べたら余計に寝れなくなったソケットの話 - Qiita
Unicorn 再起動
起動させていたのをctrl-c
で止めて、下記実行。
# bundle exec unicorn_rails -c config/unicorn.rb -E development
ちなみに-D
を付けると、バックグラウンドで実行される。
その場合、止めるときはプロセスIDを探してkill
する。
# bundle exec unicorn_rails -c config/unicorn.rb -E development -D
Nginx の設定
nginx.conf へ追記
mac で brew を使ってインストールした場合、 下記に設定ファイルがあるので開いて編集。
# vim /usr/local/etc/nginx/nginx.conf
http {
ブロック内に下記を追加する。
元から書かれているserver {
ブロックは削除またはコメントアウトすること。
http { ... upstream unicorn { # unicorn.rbで設定したunicorn.sockを指定 server unix:{RAILS_ROOT}/tmp/development_unicorn.sock; } server { listen 8080; server_name first_app; root {RAILS_ROOT}/public; access_log {LOG_PATH}/first_app_access.log; error_log {LOG_PATH}/first_app_error.log; try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn; } } ...
nginx の起動
# nginx
で起動する。
再起動は下記。
# nginx -s reload
下記にアクセスできることを確認する。
http://localhost:8080
nginx 用のログファイルにログが書かれていることを確認できれば終わり。
ホットデプロイの仕組み
Unicorn は下記サイトで説明された仕組みでホットデプロイを実現させるようだ。
unicornのpreload_app - motsatのブログ
Unicorn のプロセス A が Nginx とやり取りしてサイトが動いているとして、
SIGUSR2 を プロセス A に送ると、新しいRails環境を読み込んだプロセス B が誕生する。
プロセス A を終了させることで、Nginx とやり取りするのがプロセス B のみになり、ダウンタイムを発生させないで、アプリのリロードが行える。
コマンドライン上から再現できそうなのでやってみる。
Unicorn の設定編集
Unicorn の起動を止めて、設定ファイルを編集、下記を追加。
# vim config/unicorn.rb preload_app true # SIGUSR2 を送ってRails環境を新しく読み込ませるために必要なオプション
コマンドラインで再現する
# 起動中の Unicorn のプロセスIDを確認 # ps aux | grep unicorn tsuyaxchi 93067 0.1 0.0 2424588 408 s011 R+ 9:05PM 0:00.00 grep unicorn tsuyaxchi 92788 0.0 0.4 2576308 36896 s005 S+ 8:19PM 0:04.75 unicorn_rails worker[1] -c config/unicorn.rb -E development tsuyaxchi 92787 0.0 0.9 2572288 74912 s005 S+ 8:19PM 0:04.11 unicorn_rails worker[0] -c config/unicorn.rb -E development tsuyaxchi 92786 0.0 0.0 2481504 3700 s005 S+ 8:19PM 0:00.75 unicorn_rails master -c config/unicorn.rb -E development # マスタに対して SIGUSR2 を送る # kill -s USR2 92786 # プロセスを確認する # 92786 には master (old) と追記されている # 93092 には新しい master が誕生している # ps aux | grep unicorn tsuyaxchi 92788 0.0 0.0 2576308 3916 s005 S+ 8:19PM 0:04.80 unicorn_rails worker[1] -c config/unicorn.rb -E development tsuyaxchi 92787 0.0 0.0 2579392 3844 s005 S+ 8:19PM 0:04.58 unicorn_rails worker[0] -c config/unicorn.rb -E development tsuyaxchi 92786 0.0 0.1 2481504 4400 s005 S+ 8:19PM 0:00.75 unicorn_rails master (old) -c config/unicorn.rb -E development tsuyaxchi 93104 0.0 0.0 2423368 204 s011 R+ 9:10PM 0:00.00 grep unicorn tsuyaxchi 93100 0.0 0.1 2562604 7056 s005 S+ 9:10PM 0:00.01 unicorn_rails worker[1] -c config/unicorn.rb -E development tsuyaxchi 93099 0.0 0.1 2562604 7920 s005 S+ 9:10PM 0:00.01 unicorn_rails worker[0] -c config/unicorn.rb -E development tsuyaxchi 93092 0.0 1.2 2562604 99352 s005 S+ 9:10PM 0:03.32 unicorn_rails master -c config/unicorn.rb -E development # master(old) を終了させる # kill -s QUIT 92786 # ps aux | grep unicorn tsuyaxchi 93113 0.0 0.0 2432784 620 s011 S+ 9:12PM 0:00.00 grep unicorn tsuyaxchi 93100 0.0 1.0 2565808 84140 s005 S 9:10PM 0:00.54 unicorn_rails worker[1] -c config/unicorn.rb -E development tsuyaxchi 93099 0.0 0.9 2577340 76700 s005 S 9:10PM 0:01.04 unicorn_rails worker[0] -c config/unicorn.rb -E development tsuyaxchi 93092 0.0 0.4 2562604 32184 s005 S 9:10PM 0:03.32 unicorn_rails master -c config/unicorn.rb -E development
下記に問題なくアクセスできることを確認。
http://localhost:8080
まとめ
動作させるだけなら、非常に簡単。
ここから、パフォーマンスが出る設定値を探して行くのが、
楽しいところであり難しいところ。
あと、Unicorn はホットデプロイできる仕組みを持っているようだ。
Capistrano + Unicorn でホットデプロイする仕組みを知っておきたいので、 今度やろうと思う。
Unicornのダウンタイムなし再起動は考え無しに使うと危険 | ひげろぐ
RailsのデプロイとUnicornのトラブルシューティング | KRAY Inc