As Sloth As Possible

可能な限りナマケモノでありたい

タグ:nginx

タイトルからして既に残念な感じが漂ってるけど、前回の記事で言った通りPlackでアプリを作ってみようと試行錯誤中。ちなみにこないだサーバをApacheからnginxに変えたついでにHTTP::EngineのアプリもFastCGIで動かすようにしたので、PlackのアプリもFastCGIで動かしてみた。設定はこんな感じ。

# app.psgi
use NetaKit::TweetProxy::App;
use Plack::Builder;
builder {
    #mount '/baritter' => builder {
        NetaKit::TweetProxy::App->new->to_app;
    #};
};
#!/usr/bin/env perl
# bin/fcgi.pl
use strict;
use warnings;
use File::Spec;
use FindBin qw($Bin);
use Plack::Server::FCGI;
use lib File::Spec->catfile( $Bin, qw(.. lib) );
my $app = eval { require File::Spec->catfile( $Bin, qw(.. app.psgi) ) };
my $server = Plack::Server::FCGI->new(
    nproc       => 4,
    listen      => '/tmp/plack_netakit.sock',
    pidfile     => '/tmp/plack_netakit.pid',
    detach      => 1,
);
$server->run($app);
# nginx.conf
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /var/www/faultier.jp/htdocs;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   share/nginx/html;
    }
    location /baritter {
        set $script "";
        set $path_info $uri;
        fastcgi_pass unix:/tmp/plack_netakit.sock;
        include fastcgi_params;
    }
}

PlackのがH::EよりもRackと似たような感じに書けて楽だった。DLSとかURLMapとかもあるしね。あと、Rackで言うところのconfig.ruにあたるのがapp.psgiなんだけど、せっかくこれ書いたのにfcgi.plで同じのまた書くのやだなぁと思ってなんとなくrequireしてみたら普通に行けた。素敵。使い方これでいいのか疑問だけど。mount使おうとして上手くいかなくてコメントアウトした形跡があるのはまぁ御愛嬌。

baritter

いい加減彼女が404ばかりで飽きてきたので今回は真面目になんかしら遊べるものを作ってみることにした。

バリバリ 嘘じゃないもん

まぁアプリ名とかから推測つきそうなもんですが、ようはtwitterのポストを拾ってきてアレげなフォーマットにはめ込んで表示するだけの簡単なお仕事をするサービスです。サンプルなので単語を抽出するとかそういう凝ったことは決してやりません!(キリッ。上のスクショはそもそも元発言(もしくは発言者の脳味噌)が残念なのであんまり変わらないけど、津田さんとか池田信夫さんとかにこのフィルタをかますと脱力感が半端ないので3秒くらいは楽しめた。

ちなみに成果物はこんなだけど、内部ではPlackとText::MicroTemplateとData::ModelとCoroを使ってるとかいう、構成だけ見ると面白いサンプルになってるんだぜ。無駄遣いにも程があるぜ。出来たらソースも公開する予定。

どうやらUnicornというのが良いらしいという噂を聞きつけたので、どんなもんじゃろと試してみることにした。

Route 477 - 大規模Railsサイトのための新しいHTTPサーバ、Unicorn

Unicornてのは何者なのかと言うと、Rack及びRailsに対応したRubyのWebアプリ用のHTTPサーバ。詳しくは上の記事を読んで下さい。githubでも使ってるそうだ。あと、名前が格好良い(あんまり関係ない)。

まずはunicornの設定

と言っても、gem install unicornしてconfig.ruがあるディレクトリでunicornコマンドを叩けば、thinとかと同じようにサーバが起動する。rackup互換のオプションも付いてるので特に悩むこともないと思う。あとは普通にApacheとかでプロキシの設定してやるなりなんなりすればすぐ使える。

それだけだと大して面白くないので、折角だから上の記事に書いてあるように、nginxでソケットでっていう設定をしてみる。先にUnicornの方の設定。ちなみにサンプルに使ったのは例によって彼女が404のやつ。今現在はApache2+Passengerで動いている

# unicron.conf
worker_processes  4
working_directory '/var/www/rackapp'
listen '/tmp/rackapp.sock', :backlog => 1
listen 4423, :tcp_nopush => true
timeout 10
pid '/tmp/rackapp.pid'
preload_app  true
stderr_path '/var/log/rackapp.log'

before_fork do |server, worker|
  old_pid = "#{server.config[:pid]}.oldbin"
  if old_pid != server.pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    end
  end

  sleep 1
end

after_fork do |server, worker|
  addr = "127.0.0.1:#{4423 + worker.nr}"
  server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => 1)
end

中身はほとんどUnicornの設定例からコピペ。ちなみに、nginxを推奨してるだけあってnginxの設定に似せたDSLになってるけど、実態は見ての通りRuby。その気になれば動的に設定をごにょごにょみたいなこともできる。ログはThinみたいによしなにやってはくれないけど、その辺は設定でLoggerを渡すなりRackのミドルウェアを使ってなんとかするなりすればOK。

んでこれを適当なファイル名で保存したら、次のようにunicornコマンドを叩く。

$ unicorn -D -c /var/www/rackapp/unicorn.conf /var/www/rackapp/config.ru

-Dオプションでデーモン起動、-cオプションは設定ファイルの指定、最後の引数はrackupファイルのフルパス。ちなみにこれを/var/www/rackappじゃないところで実行してみたんだけど、最初は「working_directoryとか指定してるから、そこにあるconfig.ruを勝手に読んでくれたりしないかな」とか思ってたんだけどやっぱりダメで、その後相対パスで指定してみたらrequireでコケて「そんなファイルねーよ、寝言は寝て言え」と怒り出したので、絶対パスにしたら行けた。

この時点でhttp://localhost:4423/がちゃんと見られることと、unicorn.sockが出来てることを確認。よし次はnginx。

nginxのプロキシ設定

こんな感じ。

# nginx.unicorn.conf
upstream rackapp {
    server unix:/tmp/rackapp.sock;
}

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass  http://rackapp;
    }
}

これを大本のnginx.confのhttpのブロックのどこかでincludeしてやる。一応言っとくとこれ以外にも普通のnginxの細かい設定はしてるけど、上の例では省略してます。

ちなみに、ソケットでやるように設定してるからこうなってるけど、TCPで良ければproxy_passのところをhttp://localhost:4423とかにしてやっても普通に動く。

とりあえずこれで完成。あとはnginxを起動してやれば、ちゃんと見られる。素敵。

インターフェースが統一されてるって素敵よね

いやぁ、やっぱRackでインターフェースが統一されてるって、良いですよね。アプリ側あんまり弄らなくてもさくっと移行できるわけですし(っていう話をこないだ書いた)。あと、ついでに同じサーバで動いてたHTTP::Engineのアプリも、apache+modperlからnginx+fcgiに移行してみたけど、こっちもちょこっと設定変えたくらいでアプリ側は全然弄ってない。良いなー。こうして新しい環境が出てきたりしたときにはやっぱりRackやなんやらが真価を発揮する。折角なので次はPlackでH::Eのときと同じことをやってみようと検討中。

んで、結局Unicornは良いの?イイの?

さぁ…ベンチ取ってないのでなんとも。取っても「彼女が404」じゃあんまり参考にならないんだよなー。ただ、アプリをロードし終わってからforkするとかnginx側に気付かせない用に再起動できるとかその辺だけでも十分魅力的ではある。あと、再起動は早かった。流石。

↑このページのトップヘ