だるろぐ跡地

2009-06-19

sinatraアプリなどをapache/passenger/mod_railsで動かす

| 00:45 | sinatraアプリなどをapache/passenger/mod_railsで動かす - だるろぐ跡地 を含むブックマーク

passengerインストールして、使うためのコマンド実行。

% sudo gem install passenger
% sudo passenger-install-apache2-module

最後にこんなメッセージ。

Please edit your Apache configuration file, and add these lines:

   LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.3/ext/apache2/mod_passenger.so
   PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.3
   PassengerRuby /usr/bin/ruby

表示されるパスは環境により異なるはず。まぁ、言われる通りに上記をapacheのconfにコピペ


あとはアプリケーションルートに public tmp のディレクトリを作成、 config.ru を以下の内容で作成。

require 'start' # sinatraアプリの名前を指定
run Sinatra::Application

あとはapacheのconfに以下を追記。

<VirtualHost *:80>
    DocumentRoot "/path/to/sinatra_app/public"
</VirtualHost>

あとはapache再起動して終わり。

簡単過ぎて泣ける。 perl/apache/mod_perl/catalyst のときはあんなに苦労して調べたのに。


まあこれで終わりでもいいのだけど、やっぱり静的コンテンツ/動的コンテンツでapacheは分けるべきかと。

アクセスログ見たら、cssjpgsinatraアプリも全部同じapacheプロセス(mod_railsをロードした、メモリ食いな)が処理してたし。apacheプロセス1個だけだから当然だけど。

passengerは自動でいい感じに処理してくれるとかだったらごめん。確かtomcatだかstrutsは、何も意識しなくても処理してくれるらしいから、passengerもそうなってますよとか。

とりあえず、catalystのときとは異なり、本当にmod_railsをロードしているかいないかの違いしかないconfを2つ用意していい感じに出来た。多分、無駄があるけど、mod_railsに静的コンテンツを処理させるよりは遥かにマシなはず。

静的だの動的だの何それおいしいのって人は つ http://d.hatena.ne.jp/foosin/20090502/1241274828


あと、アプリ再起動したい場合は、apache再起動するまでも無く、 tmp ディレクトリ以下に restart.txt を置けばいい。その次のリクエスト時に自動で再起動してくれる。

再起動後、restart.txtは削除されるらしいのだけど、うちでは何度試してもされなかった。apacheが読み書きできる権限なのに。ただ、タイムスタンプを見てるっぽく、最初の1回しかアプリ再起動しない。touchなどすればまた再起動される。

開発中で毎回再起動したいーっていう場合は、 restart.txt の代わりに always_restart.txt というファイルを置けばよろしい。


参考リンク

Sinatraで鼻歌まじりのWeb開発

Phusion Passenger users guide, Nginx version (特に 7.6. Making the application restart after each request の項)

2009-06-04

設定ファイルに絶対パスを書くのを避けたい

| 22:19 | 設定ファイルに絶対パスを書くのを避けたい - だるろぐ跡地 を含むブックマーク

アプリの置いてあるパスを絶対パスで取得したい。

楽なのはconfにPerlSetEnvで書いてプログラムで$ENV{APP_PATH}とかで受け取ればいいけど、confに絶対パス書くのを避けたい。


案1:File::Spec->rel2absを使ってみる

大抵のwafで作ったアプリは起動時に1回だけ走る処理がある。Catalystのsetupみたいな。

そこで絶対パスを取得してはどうか。

$APP_PATH = File::Spec->rel2abs('..');

DocumentRootに指定したパスの1個上がアプリホームだと仮定するとこうなる。

アプリパス:/hoge/app

DocumentRoot:/hoge/app/htdocs

的な。


一見正しく動いてくれるけど、しばらくすると確実にエラーる。

理由は、子プロセスは大抵複数あるけど、その子プロセスそれぞれにおいて「起動時に1回だけ走る処理」が走るから。

例えば、子プロセス1に http://example.com/アクセスしたら $APP_PATH は /hoge/app/htdocs/.. になるが、

プロセス2が生まれた後、初めてのアクセスhttp://example.com/user/ だったら、 $APP_PATH は /hoge/app/htdocs/user/.. になる。

いやーハマったハマった。


httpd -X とかするとシングルプロセスで走るけど、デバッグ用だし重いのでだめぽ

というのを柔道家から教えてもらった。


案2:先にconfにモジュール読み込む命令書く

LoadModuleか何かで、起動時に「このファイル先に読め」的なことができるらしい。これも柔道家から教えてもらった。

が。

アプリ内で使うモジュール全部書くんですと。アプリ本体はもちろん、DBIx::ClassからTemplateまで。他も全部。

そうしないとメモリ効率が悪くなるんだそうで。

ごめんなさい逃げさせてください。


案3:`pwd`とかCwd使ってみる

案1と同じ理由で死亡。


結局confに絶対パスのベタ書きしてる今。避けたい。

2009-05-20

apache1/mod_perl1のmakeとsledge用のconf

| 19:52 | apache1/mod_perl1のmakeとsledge用のconf - だるろぐ跡地 を含むブックマーク

apache1はふつーにconfigure/makeったらdsoにならんくてmod_perlが組み込めませんでした的。

そしてapache1をまともに触るのは初。


apache

--enable-module=soでdsoに

% ./configure --prefix=/usr/local/apache1 --enable-module=so

mod_perl

% perl Makefile.PL USE_APXS=1 WITH_APXS=/usr/local/apache1/bin/apxs EVERYTHING=1

sledge用のconf

初めてなのでバーチャルホストとかIncludeとかせずにベタッと。とりあえず動かしたいのだ。

あ、ここではアプリ名がHelloで。


#LoadModule env_module         libexec/httpd/mod_env.so
LoadModule perl_module        libexec/libperl.so
#AddModule mod_env.c
AddModule mod_perl.c

ServerName hello.example.com
DocumentRoot /path_to_app/hello/htdocs

<Directory /path_to_app/hello/htdocs>
    DirectoryIndex index.cgi index.html
    PerlSetEnv PERL5LIB /path_to_app/hello/lib

    <Files ~ \.cgi$>
        Options +ExecCGI
        SetHandler perl-script
        PerlHandler Apache::Registry
    </Files>
</Directory>

warn出るが動くので良しとする。動かないよりいいのである。


すこーしだけ触ったところ、やっぱcatalyst/railsみたいなテストサーバスクリプト欲しいなと。

あとMVC分離できるのかなこれ。.pmに処理書いて.cgiから呼ぶって感じになるのかな。

dbicどうやって使えるのかなーテストはwebコンテキスト分離して書けるかなーは先の話。まずはブツを作れるようにならんと。


やったこと

2009-05-02

1台のマシン上で複数のアプリを動かすときのこととか

| 23:33 | 1台のマシン上で複数のアプリを動かすときのこととか - だるろぐ跡地 を含むブックマーク

http://yusukebe.com/archives/09/05/02/212113.html で「apache + mod_perlだと同じメモリ上にモジュールを読み込むからメモリ効率が悪いけど、lighttpd + fastcgiだとアプリごとに起動するからそんなことは無くなる」ってあったけど、アプリ1とアプリ2で別々にモジュール読むより、1回メモリ上にロードしたやつを共有した方がいいのでは?とか思ったけどapachemod_perlがよく分かってないので多分俺の誤解だろうということで後回し。勉強が足りない。後で調べる。


さておき。


うちの自宅サーバでは複数のcatalystアプリと、静的コンテンツだけを扱うapacheプロセスを立ち上げている。

mod_perlを組み込んでいないフロントエンドのapacheが1つと、mod_perlを組み込んであるバックエンドのapachecatalystアプリの数だけ。

catalystアプリのリクエストは、まず全てフロントのapacheが受け、静的コンテンツならフロントのapacheが返す。動的処理なら、バックエンドのapacheにRewriteRuleで飛ばしてる。

フロントには、あらかじめ各catalystアプリの分だけ、名前ベースのバーチャルホストを作っておく。

バックエンドのapacheは当然ポートも変えて起動しているので、RewriteRuleする際はポート指定して飛ばす。アプリ1の動的処理をアプリ2が受けるわけにはいかないので。


ロードバランサやpoundを使えば、フロントもアプリ毎に起動してもいいのだけど、フロントくらい全部一緒でええやん、なノリ。

まーフロントがアプリ毎にあるのも、1個だけなのも、どっちにも長所も短所あるので。


ときに、このフロント/バックでapacheを分けるってのはwebアプリにおいては常識なのだけど、一昨年に神に聞くまで知りませんでしたがな。

2008-11-16

apache.orgの設定通りにしなかったら成功した

| 17:07 | apache.orgの設定通りにしなかったら成功した - だるろぐ跡地 を含むブックマーク

apache.orgのサンプル

NameVirtualHost *:80

<VirtualHost *:80>
ServerName www.domain.tld
ServerAlias domain.tld *.domain.tld
DocumentRoot /www/domain
</VirtualHost>

<VirtualHost *:80>
ServerName www.otherdomain.tld
DocumentRoot /www/otherdomain
</VirtualHost>

おせーてもらった内容との大雑把なdiff

- ServerAlias domain.tld *.domain.tld

で自分のしたいことが出来た。めどいので調査はしていない

知人に感謝。