tDiaryを Nginx + Unicorn + さくらVPSで動かした
さくらVPSがリニューアルしたので、この日記も新しいサーバに引っ越した。ついでに、サーバの構成も変えてみた。
- これまで … Apache2 + FastCGI
- これから … Nginx + Unicorn
Unicornまで持ち出すのはオーバースペックな気もするけど、面白いから、いい。
インストール
- Nginx … OSをUbuntu (2012.04 LTS) にしたので apt-get nginx でインストール
- Ruby … rbenv + ruby-build で 1.9.3 をインストール
- Unicorn … rbenv環境にてgem install unicorn
- tDiary … githubからtdiary-coreとtdiary-contribを取得
サイト構成
ドキュメントルートは /var/www/www.machu.jp
に設定し、トップページのコンテンツはここに置く。
ただし、tDiary関連のファイルはドキュメントルート以下に置かない。 これがFastCGI経由とUnicorn(というかRackサーバ)経由の一番の違い。
僕は以下のサイト構成にした。
/var/www/www.machu.jp ← トップページの静的コンテンツ
/home/machu/var/tdiary
tdiary-core/ ← GitHubからtdiary-coreをpull
tdiary-contrib/ ← GitHubからtdiary-contribをpull
data/ ← tDiaryの @data_path で指定
Nginxの設定
基本設定は省略。サイトごとの設定 /etc/nginx/site-available/www.machu.jp
はこれ。 /diary/
以下をポート8080へ転送するようにしている。
upstream www.machu.jp {
server localhost:8080;
}
server {
root /var/www/www.machu.jp;
index index.html index.htm;
server_name www.machu.jp;
location ~ ^/diary/ {
rewrite ([0-9\-]+)\.html$ /diary/index.rb?date=$1 last;
proxy_pass http://www.machu.jp;
}
}
YYYYMMDD.html を index.rb?date=YYYYMMDD へ書き換えているのもここ。
Unicornの設定
tDiaryの設置場所 /home/machu/var/tdiary/tdiary-core
に unicorn の設定ファイル unicorn.conf
を作成。
元ネタはUnicornのオフィシャルサイトから入手。
worker_processes 4
listen 8080, :tcp_nopush => true
pid "unicorn.pid"
stderr_path "log/unicorn.stderr.log"
stdout_path "log/unicorn.stdout.log"
preload_app true
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
ポイントはこれくらいか。
worker_processes
: 起動するプロセス数。メモリと相談して増減。liston
: 待ち受けポート番号pid
: unicornの起動プロセスIDを書き出すファイル
tDiaryの設定
tDiaryで使用する関連ライブラリを bundle でインストールする。--without オプションを指定して、開発のみで使うライブラリ類を除外する。
$ gem install bundler
$ bundle install --without test development
次に config.ru を編集。/diary/ディレクトリ以下で動かせるように、 base_dir を指定できるようにした。(これは後で本体に pull request を送る予定)
diff --git a/config.ru b/config.ru
index 4f78176..e00c65d 100644
--- a/config.ru
+++ b/config.ru
@@ -3,7 +3,9 @@ require 'tdiary/application'
use Rack::Reloader
-map '/assets' do
+base_dir = '/diary'
+
+map "#{base_dir}/assets" do
environment = Sprockets::Environment.new
['js', 'theme', '../tdiary-contrib/js', '../tdiary-theme'].each do |path|
environment.append_path path
@@ -11,15 +13,15 @@ map '/assets' do
run environment
end
-map "/" do
+map "#{base_dir}/" do
run TDiary::Application.new(:index)
end
-map "/index.rb" do
+map "#{base_dir}/index.rb" do
run TDiary::Application.new(:index)
end
-map "/update.rb" do
+map "#{base_dir}/update.rb" do
use Rack::Auth::Basic do |user, pass|
if File.exist?('.htpasswd')
require 'webrick/httpauth/htpasswd'
次に tdiary.conf を編集。contribのプラグインを参照できるように sp.path を設定。あとはいつも通りでOK。
@options['sp.path'] = ["#{TDiary::PATH}/misc/plugin", "#{TDiary::PATH}/../tdiary-contrib/plugin"]
その他
- 認証ファイルは .htpasswd をそのまま使える。config.ruにて.htpasswdを読み込んでいる。
- unicorn経由で起動するので FastCGI と違って index.rb や update.rb の shabang 行の編集は不要。
起動
Nginxはinit.dで起動。UnicornはtDiaryのルートへ移動して、unicornコマンドで起動。-cオプションは設定ファイル読み込み。-Dはデーモン化。
$ sudo /etc/init.d/nginx start
$ cd /home/machu/var/tdiary/tdiary-core
$ unicorn -c unicorn.conf -D
いきなりunicornで動かすよりも、まずは ./misc/standalone_cgi/bin/server
や rackup
を使って単体で動かすのがいいだろう。
停止
Unicornはプロセスへのシグナル送信で操作する。Unicornのマニュアルを参照。
$ cd /home/machu/var/tdiary/tdiary-core
$ kill -HUP `cat unicorn.pid` ← 再起動する場合
$ kill -QUIT `cat unicorn.pid` ← 終了する場合
まだできていないこと
- 静的ファイルのキャッシュ (今は静的ファイルもUnicorn側で返しているが、Nginx側で返したい)
- YYYYMMDD.html → index.rb?date=YYYYMMDD の変換を Nginx 側ではなく tDiary のRackレイヤで実施
- フィード (index.rdf) が読めなくなった
abで測定
ab -n 30 -c 3
で新旧を比較。
これまで(Apache2+FastCGI)。
Requests per second: 1.19 [#/sec] (mean)
Time per request: 2529.478 [ms] (mean)
Time per request: 843.159 [ms] (mean, across all concurrent requests)
変更後(Nginx+Unicorn)
Requests per second: 5.39 [#/sec] (mean)
Time per request: 556.467 [ms] (mean)
Time per request: 185.489 [ms] (mean, across all concurrent requests)
4倍くらい速くなった。でも、サーバも変わったし、起動プロセス数も違うし、どこが効いているのかわからない ← だめな性能測定のパターン