毎秒1000リクエスト を捌く超高速CMS「adiary」
2008/12/26(金)adiary Ver2.01~2.03のサムネイルバグ
adiary Ver2.01から2.03で標準付属した設定ファイルにミスがあり、その設定ファイルを使用した場合、サムネイルを記事に貼り付けると正しいリンクが作成されない不具合があります。
ファイル名 : uploader.conf.cgi
(修正前)120行目付近 <$v.upload_tag_thumbnail = "[image#small:%i:%d:%f:%f]"> (修正後) <$v.upload_tag_thumbnail = "[image:%i:%d:%f:small:%f]">
心当たりのある方は、現在使用中の uploader.conf.cgi のファイルをご確認ください。
ずいぶん前にご指摘いただいていたのですが、確認が遅れたために報告が遅れましたことをお詫び申し上げます。
追伸
もうすぐ Ver2.04 をリリースします。
2008/03/13(木)adiaryの記法入力支援ツール
最低人間さんが作られたようです。ひとぅさんもだけど*1、みなさん早っ。
色の指定などに関しては adiary 側の色記法対応待ちでしょうか。
colorタグでも作りましょうか。
color = 色指定, ASCII, 2, <span style="color: $1">#2</span> red = 赤, ASCII, 1, <span style="color: red">#1</span> blue = 青, ASCII, 1, <span style="color: blue">#1</span> green = 緑, ASCII, 1, <span style="color: green">#1</span> yellow= 黄, ASCII, 1, <span style="color: yellow">#1</span>
コメント欄(ひとぅさん)からですが。
adiary2に取り込まれ、ユーザーごとにON/OFFが選べるようになるとベストですね。
とりあえずライセンスを教えてくださ(略)
2008/02/03(日)SpeedyCGI/FastCGI でモジュール動的更新
Satsuki-system(adiaryの基礎)で使用している、モジュールの自動更新機構と SpeedyCGI/FastCGI での実装について詳細に解説します。
モジュール自動更新の必要性
SpeedyCGIやmod_perl等々のスクリプトキャッシュ環境で実行速度が改善するのは、プログラム本体やライブラリをコンパイルした状態で内部に保持するためスクリプト実行時間の大半を占めるコンパイル時間が短縮されるというメリットがあるためです。特に最近のスクリプトは便利なライブラリを使用する傾向が強く、実行時間の95%以上がスクリプトのコンパイル時間なんてこともめずらしくありません。*1
しかしそのような環境では、スクリプトライブラリを書き換えてもプログラムは依然としてキャッシュした古いライブラリを使用し続けるので、少し書き換える度に SpeedyCGI の常駐プロセスを手動で殺したり、Apacheを再起動させたりといった手間が必要になります。
これを避けるためにはスクリプト自身でライブラリの更新をチェックし、ライブラリが更新されていた際に自動的にスクリプトを再起動(リロード)させる仕組みが必要になります。
ライブラリ更新チェック方法
Satsuki-system(adiary) では lib/Satsuki/Base_auto2.pm にその仕組みが実装されています(むしろそのファイルは、それ関連しか書かれてません)。
# AGPLv3 ####################################################### # ■SpeedyCGI / FastCGI用のリロードチェックサブルーチン ####################################################### my %lib_modtime; #------------------------------------------------------ # ●新たにロードされたライブラリの更新時間を保存 #------------------------------------------------------ sub save_lib_modtime { while (my ($pkg, $file) = each(%INC)) { if (exists $lib_modtime{$file}) { next; } $lib_modtime{$file} = (stat($file)) [9]; } } #------------------------------------------------------ # ●ライブラリが更新されているか確認 #------------------------------------------------------ sub check_lib_update { while(my ($file, $current_tm) = each(%lib_modtime)) { my $tm = (stat($file)) [9]; if ($tm > $current_tm) { return 1; # 更新されている } } return 0; }
%lib_modtime がライブラリの更新時刻を保持するハッシュです。save_lib_modtime をプログラムの終了時に呼び出し、新たにロードされたライブラリを %lib_modtime に保存しています。そしてプログラム開始時に check_lib_update を呼び出して、更新されたライブラリがあるか確認しています。
もし更新されたライブラリが発見された場合は、この実行終了後に(キャッシュされた)プロセスを終了する予約をして、リクエストされたURIにリダイレクトします。*2
#SpeedyCGI if ($self->check_lib_update()) { CGI::SpeedyCGI->shutdown_next_time(); # リクエスト終了後シャットダウン if ($ENV{REQUEST_METHOD} ne 'POST') { # POSTはリダイレクトできないのでそのまま処理 $self->redirect($ENV{REQUEST_URI}); # 同一URLにリダイレクト } }
FastCGIでの処理も同様です。mod_perlの場合はApache自体を reload させるわけにはいかないので、別の方法になっています。
なぜか更新が検出できない
SpeedyCGI のバグなのか仕様なのか、Base.pm の更新が検出できない(リロードされない)というバグに長いこと悩まされていました。SpeedyCGI は何分かアクセスがなければ自動でプロセスが落ちるためさほど深刻ではありませんが、奇妙なので少し調査してみました。
SpeedyCGIの起動ルーチンは次のようになっています。
#!/usr/bin/speedy use Satsuki::Base(); { # ルートオブジェクト生成 my $ROBJ = Satsuki::Base->new(); # SpeedyCGI向けリロードチェック $ROBJ->init_for_speedycgi('Satsuki::'); # メイン $ROBJ->start_up(); }
色々調べてみると、CGI::SpeedyCGI->shutdown_next_time(); 自体の処理は問題なく、SpeedyCGI自体はリロードがかかっているにも関わらず、Satsuki::Base がリロードされないということが判明しました。どうやらshutdown_next_time() は本当にリロードしているわけではなく、use段階は再実行しない(perlのBEGIN構文)ようです*3。
試行錯誤の末、use Satsuki::Base(); の部分を次のように書き換えることで解決されました。
if (! $Satsuki::Base::VERSION) { delete $INC{"Satsuki/Base.pm"}; require Satsuki::Base; }
ここに delete が付いている理由ですが、Base.pm のロードの途中に構文エラーなどで失敗した場合、requireしたライブラリにロード済の情報が残ったまま($INC{"Satsuki/Base.pm"}が保存されたまま)の状態でキャッシュしてしまいます。この状態ではライブラリのリロードに問題があるため、ロード情報を消してから require します。