まちゅダイアリー
2007-02-03 (土)
■ 人気の日記プラグインのバグ
先に結論から
人気の日記プラグインにバグがありました。 (多分いないと思うけど)もしお使いの方がいらっしゃったら、更新をお願いします(差分←trunk/plugin/hatena_bookmark_entry.rbの方です)。
経緯
ここ数日、日記の表示が遅くなっていた。
てっきりアクセスが集中したから(図を参照)…と思い込んでいたけど、今日になっても重いのは変わらない。
こういうときは、自分で作ったプラグインを疑うのが一番の近道、と思って一つずつプラグインを外しながらテスト。
負荷計測には、mput さんの日記に書かれている方法を参考にした。
curl を使って自分の日記にアクセスし、かかった時間を表示する。
$ time curl --silent 'http://www.machu.jp/diary/' > /dev/null real 0m3.716s user 0m0.010s sys 0m0.001s
一つずつプラグインを外しながらチェックしていく。 そして、人気の日記プラグインを外すと…。
$ time curl --silent 'http://www.machu.jp/diary/' > /dev/null real 0m0.551s user 0m0.000s sys 0m0.008s
うわっ。こいつが犯人だったか。 右サイドバーに表示している「人気の日記」も最近更新されていなかったし、変だと思ってたんだ。
調べてみる
$ ls -l ~/var/tdiary/cache/hatena/ total 10720 -rw-r--r-- 1 machu users 10836365 Feb 3 06:25 bookmark.dat -rw-r--r-- 1 machu users 22162 Dec 27 2005 cache-rss.xml -rw-r--r-- 1 machu users 7596 Oct 10 14:29 hatena_bookmark.dat
ちょ…10Mのファイルができてる。 bookmark.dat は、www.machu.jp の注目エントリーの RSS を解析した結果(最近人気になった日記のタイトルとURL)を保存しているPStore形式のファイル。 数KBのデータのはずなのに。
プラグインのソースを読むと、ありえないミスをしていたことに気がつく。
hatena_bookmark_open_cache(cache_path) do |db| db[sort] ||= [] (かなり略) db[sort].push({ :url => url, :title => title }) (略) end
配列は最初に一回作って、後はひたすらデータを追加しているだけだ… orz ここは日記を更新する度に呼ばれるので、日記を書くたびにデータが増えていってたことになる。 これは重いはずだよ。
ということで、
- db[sort] ||= [] + db[sort] = []
と修正し、 bookmark.dat を削除してもう一度速度を計ってみる。
$ time curl --silent 'http://www.machu.jp/diary/' > /dev/null real 0m0.536s user 0m0.008s sys 0m0.001s
うん。直ったみたい。 しかしなぁ…。 さくらインターネットさん、負荷かけてごめんなさいごめんなさい。
■ 人気の日記プラグインの名前
hatena_bookmark_entry.rb じゃ分かりにくいので、 popular.rb みたいにした方がいい気がしてきた。 はてなブックマークからの結果だけで popular を名乗っていいのかどうかは疑問だけど。
■ TextDrive でサブドメイン (lighttpd 編)
hsbtさんの日記より。
.htaccess で小細工対処ではなくてサブドメイン申請したりなんだりしないとダメかなあ
TextDrive のサブドメインの仕組みは少し癖があるんだよね。 詳しくはTextDrive でサブドメインに書いたけど、メインディレクトリの下に作ったディレクトリがサブドメインの置き場になる。
web/public/ ← www.example.com のコンテンツを置く web/public/diary/ ← diary.example.com のコンテンツを置く
この仕組み、一見すると www.example.com/diary/ と diary.example.com/ で同じコンテンツが見られて Good と思える。 でも、 .htaccess を使って www.example.com/diary/ を diary.example.com/ にリダイレクトしようと考え出すと、とたんに罠にはまる。
- web/public/diary/ に .htaccess を置く
- ↑に www から diary のリダイレクトを書く
- diary でも同じ .htaccess が参照される
- www と diary を区別するために RewriteCond %{HTTP_HOST} を使う
- でも何故かうまくいかない ← いまここ
単純に、僕が mod_rewrite の使い方を理解していない可能性もあるけど。 もしかしたら、UseCanonicalName を offにすれば上手くいくのかもしれない。
でも、最近は Apache を使わずに全部 Lighttpd でやればいいんじゃないかと思うようになってきた。
ようやく本題 (lighttpd でサブドメイン on TextDrive)
TextDrive では、自分専用の lighttpd を動かすことができる。 ポート番号は 8765 のように 80 以外になるので、 80 で動いている共用の Apache からプロキシで接続することになる。
まずは、 Apache で受けたリクエストを、すべて lighttpd にリダイレクトさせる。 web/public/.htaccess は以下の通り。
RewriteEngine on RewriteRule (.*) http://127.0.0.1:8765/$1 [P,L]
次に lighttpd での振り分け方を考える。 そもそも web/public/diary/ を www と diary で共用しているから無理が出てくる。 両者を別のディレクトリに分ければ問題は解決するんじゃないかな。 ってことで、 etc/lighttpd/lighttpd.conf にこう書く。
var.base = "/users/home/" + server.username HTTP["host"] =~ "www\.example\.jp" { server.document-root = base + "/web/www.example.jp/public/" } HTTP["host"] =~ "diary\.example\.jp" { server.document-root = base + "/web/diary.example.jp/public/" }
こうすることで、
web/www.example.jp/public/ ← www.example.com のコンテンツを置く web/diary.example.jp/public/ ← diary.example.com のコンテンツを置く
という構成になる*1。
後は、 web/www.example.jp/public/diary/ にアクセスされたら diary 側に飛ばすように書けばいいんじゃないかな。 リダイレクトせずに同じコンテンツを見たいのなら、シンボリックリンクを張ればいい訳だし。
全て lighttpd に飛ばして、 lighttpd 側でサブドメインごとに振り分けるところまでは試した。
注意点として
TextDrive のサーバはたまに再起動するので、 lighttpd が自動的に起動するようにしていた方がいいかも。本家のマニュアルに書いてあった。
*1 さくらのレンタルサーバでサブドメインを使う場合と同じような構成
リンク先のプラグインのURLが間違っているようで trac に怒られてしまいました。
あー。(二重の意味で)ごめんなさい。<br>直しておきました。