ratio - rational - irrational

« PICSY、ニコニコ経済、ハッカー経済と呼ばれる何かのものたちについての考察結果 | Main | 本を探す »

2007年11月03日

Rails勉強会@東京第23回

Rails勉強会@東京第23回に行ってきた。2週間遅れだけどレポートする。

勉強会の形式はいつものごとく

ただ、今回は試験的に「昼食懇親会」を行なった。

  • そこで話しているうちにうち解けてセッションが弾むのでは?
  • セッションの時間を潰して長い自己紹介をしなくても、自然に相手を認識できるのでは?
  • セッション案も自然に出てくるのでは?
  • 夜の「飲み会懇親会」よりも安く済むのでは?

という趣旨だ。おおむね好評だった模様。ただ、私はどうも元気が出なくて遅れていったので懇親会は殆ど出てない。



前半

前半は3つのセッションに分かれた。

  • Rails 2.0を読む。
  • 初心者セッション - Scaffoldの半歩先に
  • ぐだぐだ喋る

初心者セッションは前回と同じ内容だそうだ。Scaffoldは試してみたけれどもその先へ進めないというRails初心者のために、Scaffoldで生成されたモデルやコントローラーを解説して、自力でコードを書くところまで持って行くという趣旨。

前回に引き続いてオーナーをやってくださってるYuumi3さんには乙! で、今回もScaffold結果の解説だけで時間切れみたい。このやり方はRailsの初心者向け解説としては理想的だと思うけど、時間は意外に掛かるのね。masuidriveさんが言ってるけど、「自分でやるだけなら5-10分で終わること」が限界な訳か。

余った部屋に溜まってぐだぐだ雑談するセッションはなんか好例になってきたけど、この企画はとても良い。ぐだぐだ喋っているうちに色々とアイディアが湧いてきて、その場に集まってる人の知恵を結集してもの凄い勢いで解析が進んだり、プロダクトができあがったりする。

今回は昼食懇親会をやった関係上、懇親会とぐだぐだセッションは地続きだったらしい。その様子はshachiさんがレポートしてる

この手のイベントは結局、懇親会とかでする雑談が一番大切だったりするわけだよね。ぐだぐだセッションはそのメリットを勉強会時間内に取り入れる試み、とも言える。

Rails 2.0

さて、雑談セッションを褒めておいて何だけど、私はRails 2.0セッションのオーナーをやった。

現在Rails 2.0のPreview Releaseが出ているのでそれを眺めてみようというセッション。

私は2.0変更点を全然把握してないので、詳しいことは諸橋さんたちに教えて貰いながらセッションを進めた。前にも書いたけど、Rails勉強会@東京ではこういうタイプのセッションオーナーは大歓迎なのだ。つまり、「これを知りたいから誰か教えてください」と言ってセッションを開いて、それで色々質問するいうやりかた。みんな恐れずにどんどんセッションを主催して欲しい。

で、結論としては、Rails 2.0はそれほど驚きはない。

  • ActiveResourceが入った
  • プロプライエタリなDBMSへのドライバはプラグインに追い出した
  • acts_as系はプラグインに追い出した
  • テンプレートのファイル名規約が変わった。(古い規約も認識するみたい)
    • 〈テンプレート名〉.〈出力フォーマット拡張子〉.〈テンプレートエンジン拡張子〉
    • 例えば、今までの"list.rhtml"は"list.html.erb"になる。
  • Migrationが格好良くなった。

いくつかの変更点について該当部分のソースコードを呼んでみたけど、普通。なんというか、驚きがない。ま、順当に進化したということなんだろうね。

xibbarさんのスライドが非常に詳細なので、こちらを参照。セッションでもこのスライドをみんなで見ながら進めさせてもらった。

あとはid:faultierさんのレポートが詳しい。

詳細な資料があるので私はこれ以上は書かない。



後半

後半は4つのセッションに分かれた。

  • 初心者セッション - プロダクション環境の構築
  • engineからgeneratorへの移行
  • プロファイルの話
  • 開発環境の話

私は、「プロダクション環境」のオーナーになった。Railsアプリケーションの開発の仕方はスクリーンキャストやなんかで色々と出回ってるのに対して、実際にアプリケーションを運用する方法はそこまでは出回ってない(いや、探せばそれなりにあるけど)。これを1つ説明しましょう、というセッション。

予め自サーバーに仕込んでおいて、実際にサーバーの設定をいじくって見せながら解説した。

以下における仮定

  • 環境はDebian etch。
  • サーバーはrails-tokyo-23.yugui.jpというサーバー。
  • Railsのデプロイ先は/var/rails-toky-23/current/というディレクトリ

また、次の知識を前提とする

  • Railsでscaffoldして中身を眺めるくらいはやったことがあること。
  • Apacheの設定をなんとなくは弄ったことがあること

ちなみに、世間ではこの手のお手軽サーバーにはCentOSが人気だけど、偏見を承知で言うなら断然debianだ。私にはサーバーにCentOSとかましてFedoraを使う意味が分からない。yumって重いし機能もapt-get相当でしょ? Debian系なら更に楽なaptitudeがあるんよ!! 「枯れてる+サポート」でRedhatを取るなら分かるけど。でも、典型的な構成を作ってそのまま使うならともかく、あれこれと試すためのサーバーにはDebian系がいい。DebianかUbuntuだ。

運用環境の選択肢

運用環境選択肢として今回は次を紹介した。

  • WEBrick
  • Mongrel
  • mod_proxy_balancer + Mongrel
  • Apache + FastCGI
  • Lighttpd + FastCGI

以下ではこれらの選択肢を順番に触れていく。


WEBrick, Mongrel

Railsの開発用サーバーとしてはWEBrickとMongrelが主流である。個人のちょっとしたサービスならこの開発用サーバーをそのままdaemon化しても十分である。

セッションで聞いてみたら、開発にはWEBrickを使っている人が多かった。WEBrickはRuby 1.8標準添付なのでどこでも動くし、便利だね。

でも、どうせならMongrelを使ったほうが起動が速くていい。Mongrelは主にRailsのために作られた簡易HTTPサーバーだ。一部のコードをC拡張ライブラリとして書いてるのと、機能を絞り込んである分だけWEBrickより速い。

Mongrelのインストールは

# gem install --include-dependencies mongrel

するだけ。Mongrelをインストールするとscript/serverはデフォルトでWEBrickの代わりにMongrelを使うようになる。Mongrelインストール後に敢えてWEBrickを使いたい場合は

$ ruby script/server webrick

とやる。

まあその辺は好みで。-dオプションを渡せばscript/serverはdaemonになるので

# ruby script/server -p 80 -e production -d

とかやればそれだけで運用環境になる。WEBrickやMongrelは、Rails呼び出し部分はシングルスレッドで処理するので限界はあるけれど、秒あたりのページビューが1桁ならまあ、使える。

詳しくはruby script/server --help参照。


mod_proxy_balancer + Mongrel

さて。Apacheのバージョンを2.2に上げられるならmod_proxy_balancerは良い選択だ。2.2で導入されたApache標準のモジュールで、ApacheのProxy機構に簡易ロードバランサー機能を組み込んでくれる。

    apache ──────(HTTP)───┬─ mongrel
(proxy_balancer)                  ├─ mongrel
                                  ├─ mongrel
                                  ├─ ...

この構成は

  • Apacheをフロントに立てる
    • Apacheは画像やスタイルシートなどの静的コンテンツへのリクエストを捌く。
    • 残りの動的コンテンツへのリクエストをMongrelに委譲する。
  • Mongrelは複数立ち上げておく
    • Mongrelプロセス内でRailsを動かす。
    • Apacheのmod_proxy_balancerの機能によってmongrelへリクエストをロードバランスさせる。
設定例:
<Proxy balancer://mongrel_cluster>
	BalancerMember http://127.0.0.1:8000
	BalancerMember http://127.0.0.1:8001
	BalancerMember http://127.0.0.1:8002
	Order allow,deny
	Allow from all
</Proxy>
<VirtualHost *>
	ServerAdmin webmaster@yugui.jp
	ServerName rails-tokyo-23.yugui.jp
	ServerSignature On
	
	DocumentRoot /var/rails-tokyo-23/current/public
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	<Directory /var/rails-tokyo-23/current/public/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride None
		Order allow,deny
		allow from all
	</Directory>
	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn
	CustomLog /var/log/apache2/rails-tokyo-23.access.log combined
	ErrorLog /var/log/apache2/rails-tokyo-23.error.log
	RewriteEngine on
	RewriteLog /var/log/apache2/rails-tokyo-23.rewrite.log
	RewriteLogLevel 1
	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]
	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA]
	# Rails cached pages
	RewriteRule ^([^.]+)$ $1.html [QSA]
	RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
	RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
	ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
</VirtualHost>

ま、VirtualHostの一般的な設定部分はおいといて。

DocumentRoot /var/rails-tokyo-23/current/public

DocumentRootにはRailsのpublicディレクトリを指定する。静的ファイルはApacheが取り扱うからだ。

冒頭の<Proxy>部分が肝だ。ここで3つ並べたMongrelに適宜振り分けるように設定しておいて、で、あとでここの'balancer://mongrel_cluster'っていうところにmod_rewriteで飛ばすんだな。

mod_rewriteは、Apache内部でリクエストURIを書き換えて柔軟にリクエストを処理するための標準モジュールだ。まぁそのセッションに来ていた人はみんな知っていたみたいだけど

じゃ、そのmod_rewrite部分を見ていこう。

	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]

これは、public/system/maintenance.htmlというファイルが存在したら今サイトはメンテナンス中ということなのでmaintenance.htmlの内容を出力して終わり、という話。

	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA]

それから、indexページのキャッシュが存在したらそれを使うとか。

	# Rails cached pages
	RewriteRule ^([^.]+)$ $1.html [QSA]

リクエストに拡張子が付いてなかったらHTML扱いするとか。

この辺はRails標準のpublic/.htaccessからコピーしてきてちょっと手を加えただけ。

railsコマンドでアプリケーションの雛形を作った時点でpublic/.htaccessっちゅうのが作られてるんだけど、何にしてもRailsの配備設定はこのpublic/.htaccessがとても参考になる。

さて、それで最後のところね。

	RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
	RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

リクエストにマッチするファイルが存在したら、Railsがキャッシュを作っていると判断してそのファイルをそのまま返す。

この時点で、先の書き換えによって確実に拡張子が付いているので、Railsがページキャッシュを作っていればpublic/controller_name/action_name.htmlとかいう名前で存在するはずで、%{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-fによってキャッシュの有無を判別できるのだ。

ファイルが存在しなかったらこれは動的ページへのリクエストである可能性があると判断してmongrelに転送する。終わり。


バックグラウンドMongrel

じゃあ、バックグラウンドのMongrelプロセスはどうやって立ち上げるのか。私はセッションではcapistranoで立ち上げてしまった。

capistranoを使わないなら、バックグラウンドのmongrelの立ち上げにはmongrel_clusterがいいだろう。これもgemで入れられる。

# gem install --include-dependencies mongrel_cluster

設定とか詳しいことはバリケンさんとこ参照!

capistrano

セッションで使ったcapistranoの設定は公式サイトの記述を参考にした。

こんな感じのscript/spinを作って、

#!/bin/sh
`dirname $0`/process/spawner -a 127.0.0.1 -p 8000 -i 3

config/deploy.rbをこんな感じに編集して

set :application, "example"
set :repository,  "http://svn.yugui.jp/misc/trunk/example-app"
# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/rails-tokyo-23"
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion
role :app, "rails-tokyo-23.yugui.jp"
role :web, "rails-tokyo-23.yugui.jp"
role :db,  "rails-tokyo-23.yugui.jp", :primary => true
set :ssh_options, :port => 422
set :use_sudo, false
namespace :deploy do
  task :restart, :roles => :app do
    stop
    start
  end
end

capistranoについては今回は深くは触れない。希望者がいたら次回の勉強会でセッションやろうかな。以前のRails勉強会でやったセッションの記録もあるので参照。

RailsによるアジャイルWebアプリケーション開発 第2版』にも載ってるけど、最新版のcapistrano 2.0には対応していないので注意。まあ、1.1の設定でも基本的には動くからいいんだけど。

一度慣れてしまうと手でちまちまサーバー起こしたり止めたりメンテナンス画面出したりやってられないので私は今回もcapistrano使いました、というだけ。Railsアプリケーションのデプロイ自体は単にソースツリーをサーバーにコピーすればいいのでcapistranoを使わなくてもscpでも済む。



Apache + FastCGI

Mongrel以前に主流だった手法だ。今も愛用している人はいる。

構成はこんな感じ。apacheと、バックグラウンドのワーカープロセスをFastCGIプロトコルで繋ぐ。

  apache ──(Fast CGI)─┬─ worker
                        ├─ worker
                        ├─ worker
                        ├─ ...

FastCGIを使うにはまず、ApacheのFastCGI用のモジュールを用意する必要がある。Apache用のFastCGIモジュールにはmod_fastcgiとmod_fcgidがあるが、ここではmod_fcgidを使用する。mod_fastcgiはなんか開発止まってるらしい?

ワーカープロセスは予め立ち上げておくパターンと、apacheに管理させるパターンがある。私はapacheに任せるのが楽で好き。ワーカーが死ぬと適当に立ち上げてくれたりもするしね。ま、そのへんは本来はdaemontoolsや本式な死活監視システム使えという話かも知れないけど。

Debianならインストールはapt-getするだけ。

# apt-get install libapache2-mod-fcgid
設定例
<VirtualHost *>
	ServerAdmin webmaster@yugui.jp
	ServerName rails-tokyo-23.yugui.jp
	ServerSignature On
	
	DocumentRoot /var/rails-tokyo-23/current/public
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	<Directory /var/rails-tokyo-23/current/public/>
		Options Indexes FollowSymLinks MultiViews ExecCGI
		AllowOverride None
		Order allow,deny
		allow from all
		FCGIWrapper "/var/rails-tokyo-23/current/public/dispatch.fcgi" .fcgi
		RewriteEngine On
		RewriteRule ^$ index.html [QSA]
		RewriteRule ^([^.]+)$ $1.html [QSA]
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
	</Directory>
	Addhandler fcgid-script .fcgi
	DefaultInitEnv RAILS_ENV production
	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn
	CustomLog /var/log/apache2/rails-tokyo-23.access.log combined
	ErrorLog /var/log/apache2/rails-tokyo-23.error.log
	RewriteEngine on
	RewriteLog /var/log/apache2/rails-tokyo-23.rewrite.log
	RewriteLogLevel 9
	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]
	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA,L]
	ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
</VirtualHost>

<Proxy>が消えた以外はmongrelのときと、おおまかには変わってないね。特に静的コンテンツ周りのmod_rewrite設定は。

変わったのは<Directory>内のこの部分だな。

  FCGIWrapper "/var/rails-tokyo-23/current/public/dispatch.fcgi" .fcgi
  
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

mongrelへのプロキシの代わりにワーカープロセスにリクエストを回すようにしたんだな。ワーカープロセスの実体であるdispatch.fcgiはrailsコマンドが最初にpublic/内に生成してくれてる筈。



Lighttpd + FastCGI

もう1つ人気のある構成例としてはLighttpdを使うものがある。

LighttpdというのはApacheよりも軽量なwebサーバー実装で、LLなwebアプリケーションの配備環境としては結構有力だ。"Lighttpd"(らいとえいちてぃーてぃーぴーでぃー)は発音しづらいのでみんなLighty(らいてぃー)と呼ぶ。

LighttpdはApacheよりは機能が少ないが、その分だけ軽量で配信も速い。mongrelがあちこち実装をさぼっているのとは違って本式のwebサーバーだ。高負荷時の安定性ではApacheに劣るという意見もあるが、まぁ、通常は大丈夫だ。

LighttpdはFastCGIモジュールが標準で付いている上に、活発にメンテナンスされている。これがRailsやなんかのデプロイ環境として人気を集める理由だろう。

多くのLinuxディストリビューションではパッケージ化されていて、Debianでも

# apt-get install lighttpd

だけで入る。

設定例

設定というか、Lighty + FastCGI を走らせる一番簡単な方法はRailsアプリケーションのディレクトリで

# ruby script/server lighttpd -p 80 -e prouction -d

とかやることだ。自動的にconfig/lighttpd.confが生成されて、これを読み込んでLighttpdが立ち上がる。FastCGIのワーカープロセスはLighttpdが管理してくれる。

この要領で開発用サーバーにもLighttpdを使っている人もいる。何しろ、Railsの場合はdevelopment環境ではアプリケーションサーバーの再起動が必要になることは希だし、困らないんだな。もし再起動が必要になってもLighttpdは起動もApacheより速いし。

それでもまあ、自動生成されるのと同様の設定を/etc/lighttpd.confにしてやっても良い。

Apacheの設定とは文法がかなり異質だけど、条件節を書けたりしてプログラム的でちょっと面白い。

$HTTP["useragent"] =~ "^(.*MSIE.*)|(.*AppleWebKit.*)$" {
  server.max-keep-alive-requests = 0
}
$HTTP["url"] =~ "^/doc/|^/images/" {
	dir-listing.activate = "enable"
}

初期状態の設定ファイルからrailsアプリケーションに対応してやるなら、以下のような感じ。

  1. server.modulesの読み込みリストにmod_fastcgiを足す。
  2. FastCGIの設定として次を追記。
server.error-handler-404 = "dispatch.fcgi"
fastcgi.server =  (
	".fcgi" => (
		(
			"min-procs" => 1,
			"max-procs" => 3,
			"socket"    => "/var/run/lighttpd/rails.sock",
			"bin-path" => "/var/rails-tokyo-23/current/public/dispatch.fcgi",
			"bin-environment" => ( "RAILS_ENV" => "production" )
		)
	)
)

ポイントは"404 Not Found"のハンドラとしてFastCGIを設定してやることだな。これはApacheのときに「キャッシュファイルがなかったらmongrelに転送」とか書いたのと同じこと。



他の選択肢

Pound

Pound + Apache + Mongrelというのもあるが、どうも微妙だと思うので時間の都合もあって紹介しなかった。Poundっていうのは軽量のロードバランス・ソフトウェア実装。この場合は構成は次のようになる。

  Pound ─┬─ Apache
           ├  mongrel
           ├  mongrel
           ├  mongrel
           ├  ...

Poundを使うパターンは『RailsによるアジャイルWebアプリケーション開発 第2版』に載ってるので必要ならそっちを参照。

微妙というのは、つまりロードバランスをPoundに追い出すほどの負荷がApacheに掛かることはあるのかな、ということ。RailsアプリケーションでApacheがボトルネックになることは少ないんじゃなかろうか。だとすると、ロードバランサはmod_proxy_balancerでいいじゃないかと思う。

まあ、Apachetが2.1だったり1.x系統だったりしても使えるという利点はあるかも知れない。でも、2.1ならもう潔く2.2に上げちゃいなYO!

SCGI

SCGIというWebサーバー - アプリケーションサーバー間通信のためのプロトコルがある。FastCGIやmod_jkと位置づけとしては同じだ。これのruby版サーバーライブラリとかrails対応というのもある。

けれども、これの作者のZed Shawが結局、mongrelを作ってそっちに移行してしまった。

作者としてmongrelのほうがいいという判断でそっちをメインにやるのであるなら、今後のメンテナンスが不安だ。おすすめしない。

AJP

AJPというプロトコルもある。Apacheモジュールの実装であるmod_jkの名前でも知られている。FastCGIやSCGIと同じ位置づけだ。ApacheとJava Servletコンテナを繋ぐのによく使われている。これのruby版サーバーライブラリとrails対応は私が書いた。

でも、まだ不安定だし、速度も出ないし、そんな状態で放置しているのでおすすめしない。でもApacheサイドでJavaの知見を活かせる技術であるわけだし、私としてはAJPの逆襲をやるつもりはある。そのうちおすすめできるようになったらまた記事を書く。



飲み会

今回は懇親会を昼にやったので、飲み会はとくに呼びかけなかった模様。それでも行きたい人はそれぞれ飲みに行ったみたいだけど。

私は、なんか不安症状とか疲労感がひどかったので早々に帰ってしまった。というわけで飲み会での雑談&与太話は無し。

なんか、勉強会の途中からどうしようもなく疲れを感じて、いつにもましてボソボソと喋ってたと思う。聞きづらくてすんません。


参考資料

Official Documents:

Apache 2.2
Apache設定の資料としては何を置いてもまず公式のドキュメントだ。丁寧だし、主なところは日本語版があるし。
Lighttpd
こちらも設定に必要な一通りのことは公式ドキュメントで十分。(英語)
Capistrano
Capistranoは本記事執筆時点では公式サイトのドキュメントはあんまり充実してない。(英語)

Books:

Agile Web Development with Rails, 2nd Ed. (RailsによるアジャイルWebアプリケーション開発 第2版)
第2版ではデプロイに関する記述が充実した。Poundを使ったパターン、およびCapistranoについて解説している。
Mongrel
オライリーのPDF書籍。(英語)
Capistrano and the Rails Application Lifecycle
オライリーのPDF書籍。昔、Railsのオンラインマニュアルサイトに置いてあったcapistrano解説をまとめたっぽい。Capistrano 1.2対応。2.0は対応していない模様。

Reports:

Rails under "Production"
Rails勉強会用に昔もろはしさん(id:moro)がまとめてくれた資料。
Rails勉強会@東京 #18
舞波さんによる勉強会ログ。各種運用環境の長所・短所を検討した。
LiteSpeed
激速httpdであるLiteSpeedとRailsの組み合わせの解説。
運用サーバー速度比較
舞波さんによる多様なhttpdの比較。


トラックバック

この記事のトラックバックpingのURL:
http://idm.s9.xrea.com/blog/mt-tb.cgi/689

コメント

新しくコメントをつける

よくわからない理由により、コメントが即座には反映されないかもしれませんか゛、ボタンを押して元の画面に戻ってきたならたぶん正しく送信されています。




blog操作

検索


カテゴリー

このブログについて

あわせて読みたい

follow yugui at http://twitter.com
© 2007 Yugui

Powered by Movable Type 3.2-ja-2