社内勉強会でUnicornについて発表したけどあまりの準備不足に全俺が泣いたので少しずつまとめていく〜その1

Unicornとは?

今回取り上げることにしたUnicornとは、Rubyアプリケーションサーバのこと。Unix系OS上で動作するRack規格Rubyアプリケーションを動かすためのアプリケーションサーバ
スレッドやイベント駆動を駆使した実装ではなく、伝統的(?)なprefork型のアーキテクチャを採用している。

低速ネットワーク環境にあるクライアントからの利用などは考慮していない。十分高速なクライアントを相手にする場合にうまく機能する様に設計されている。
これは、複雑さを排除するためにスレッドやイベント駆動を採用しなかったことの裏返しでもある。

unicornコマンド(もしくはunicorn_railsコマンド)でサーバを起動させる。--config-fileで設定ファイルを指定することができる。

$ unicorn -c unicorn.conf.rb config.ru

サーバが起動すると、マスタプロセスが作られ、マスタプロセスをforkしてワーカープロセスが作られる。
下図ではTCP Socketと書いてあるが、Unixドメインソケットを使うこともできる。

Reverse Proxy
 └TCP Socket[0.0.0.0:8080] > Unicorn(Master)
  ├(fork)─Worker[0] < TCP Socket[0.0.0.0:8080]
  ├(fork)─Worker[1] < TCP Socket[0.0.0.0:8080]
  &#9478;
  └(fork)─Worker[N-1] < TCP Socket[0.0.0.0:8080]

ワーカーはマスタのリスナが受付可能か確認し、受付可能ならリクエストを処理することになる。

そのほか、READMEに書かれている特徴から抜粋していかに箇条書きをして締めくくる。詳細は次回以降、適宜触れていく。

  • Unix系システムで動作させるRackアプリケーション用に設計されている
    • クライアントは高速である前提(ネットワーク距離が遠かったり、回線速度が遅かったりしない、など)
    • OSやリバースプロクシやRackフレームワークでできることは任せる
  • Rubyは1.8と1.9の両方に対応している
  • プロセス管理について
    • アプリケーションに問題があって終了したワーカーの片付けや起動を行ってくれる
    • サーバリソースが許す限りのワーカーを用意することができる
  • リクエストが処理中のワーカーにばかり割り当てられることがないようにロードバランスするのはOSカーネルに任せる
  • アプリケーションがスレッドセーフであるか気にする必要がない
  • Rack wrapperを使って古いバージョンのRackによるアプリケーションもサポートできる
  • USR1シグナルによってログを開き直す仕組みが組み込みで用意されている
    • リネームによるログローテーションを行える
  • Nginxの様にコネクションを切断せずにバイナリアップグレードを行える
  • fork前後のフックとしてbefore_fork/after_forkを利用できる
    • preload_appが偽である場合は不要(preload_appが偽ならforkの度にアプリケーションをビルドする)
  • preload_appを真にしてcopy-on-writeと相性の良いメモリ節約術が可能
  • デバッグ用にafter_forkでフックワーカー個別にプライベートなポートをバインドすることができる
  • 設定ファイルはシンプルなRuby DSL