«前の日記(2007-02-02 (金)) 最新 次の日記(2007-02-04 (日))»  

まちゅダイアリー


2007-02-03 (土)

人気の日記プラグインのバグ

先に結論から

人気の日記プラグインにバグがありました。 (多分いないと思うけど)もしお使いの方がいらっしゃったら、更新をお願いします(差分←trunk/plugin/hatena_bookmark_entry.rbの方です)。

経緯

burst traffic ここ数日、日記の表示が遅くなっていた。 てっきりアクセスが集中したから(図を参照)…と思い込んでいたけど、今日になっても重いのは変わらない。 こういうときは、自分で作ったプラグインを疑うのが一番の近道、と思って一つずつプラグインを外しながらテスト。 負荷計測には、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 編)

HUIS TEN BOSCH

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 さくらのレンタルサーバでサブドメインを使う場合と同じような構成

本日のツッコミ(全2件) [ツッコミを入れる]
しばた (2007-02-03 (土) 00:02)

リンク先のプラグインのURLが間違っているようで trac に怒られてしまいました。

まちゅ (2007-02-03 (土) 01:14)

あー。(二重の意味で)ごめんなさい。<br>直しておきました。