• 更新:
  • 投稿:
  • カテゴリィ:

動的生成時の .htaccess ファイルを見直す

今回は、ちょっと難しいよ! でも、Movable Type で動的生成(ダイナミック・パブリッシング)を利用している人は必見です。

MT で動的生成を利用する設定にすると .htaccess が自動的に作成されます。初期状態のままだと、思いっきりサーバに負担がかかるかも知れない──ということを発見しました。特に Perl 版ダイナミック・パブリッシングを使っている人は、とんでもないことになっているかも。──悪いのは、みんな spammer ですが……。

具体的には、.htaccess ファイルにこんな設定を施す、という提案です。

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

# 下の三行を追記
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jp*g|png)$
RewriteCond %{REQUEST_URI} !^/mt/cm/.*$
RewriteCond %{REQUEST_URI} !^/mt/tb/.*$

RewriteRule ^(.*)$ /mt-dynamic.php [L,QSA]

では、順を追って解説してみます。

まずはおさらい

MT3.2 で動的生成を使う設定にすると、ブログのルートディレクトリに下記の内容が書かれた .htaccess ファイルが作成されます。一部、抜粋しました。

RewriteEngine on

# don't serve mt-dynamic.php if the request is for a real directory
# (allows the DirectoryIndex lookup to function)
RewriteCond %{REQUEST_FILENAME} !-d

# don't serve mt-dynamic.php if the request is for a real file
# (allows the actual file to be served)
RewriteCond %{REQUEST_FILENAME} !-f

# anything else is handed to mt-dynamic.php for resolution
RewriteRule ^(.*)$ /mtview.php [L,QSA]

コメント部分(行頭が # から始まる行)を眺めて、重大なことに気がつきました。簡単なので一行ずつ見ていきます。

まず、RewriteEngine onApache module mod_rewrite を使う、という宣言です。

コメント部分を飛ばして、次の RewriteCond %{REQUEST_FILENAME} !-d は「ディレクトリが存在しない場合」という意味です。-d が「ディレクトリ」で ! が否定ですね。

この場合の「ディレクトリ」というのがちょっとややこしいです。このブログでいうとトップページは http://asiamoth.com/mt/ ですが、実際のアドレスは http://asiamoth.com/mt/index.php です。こういう具合に「ディレクトリのインデックスファイル」を含めて存在チェックをしています。ということで、正確には「リクエストがディレクトリの場合は、そのディレクトリにインデックスファイルが存在しない場合」ですかね(長っ)。

さらに、次の RewriteCond %{REQUEST_FILENAME} !-f を見てみます。-f が「ファイル」、! が否定なので、「ファイルが存在しない場合」ですね。

ということで、リクエストされたディレクトリ、またはファイルが存在しなければ、mtview.php に渡して、処理してもらうわけです。

──ここで何が重大なことか気がついた方は鋭い。そう──ということは、デタラメな URL や(ワケあって)削除したファイルにアクセスがあった場合でも、わざわざ mtview.php にアクセスしに行きます!

Perl版ダイナミック・パブリッシングの場合

Perl 版ダイナミック・パブリッシング を利用している場合、上記の mtview.phpmt-dynamic.php に書き換えます。

──ということは、存在しないディレクトリやファイルのリクエストがあった場合、mt-dynamic.php が処理を開始します。そして、その度に mt-dynamic.php はデータベース(各種 SQL)にアクセスして、どのような処理を行うか、確認しに行きます──。

ちゃんと、「動的生成する」と決めたテンプレートから生成される URL であれば、そのまま動的生成を行います。しかし、例えば、延々と無効な URL」にアクセスがあった場合は……?

ガクブル モノですが、その度に mt-dynamic.php くんはデータベースに問い合わせに行くわけです……。お、恐ろしい。というか、ずっっっっと、このブログではそうなっていました。何度「MySQL へのアクセス大杉」というメッセージを見たことか……。

とりあえずの解決策

さて、サクッと解決、といきたいところ。妥協案の一つはこんな感じ。

# @asiamoth
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jpe?g|png)$
RewriteCond %{REQUEST_URI} !^/mt/cm/.*$
RewriteCond %{REQUEST_URI} !^/mt/tb/.*$

2007-01-12T13:01:31+09:00 追記

はい、また嘘コード書いてました(コメント欄参照 : あんちもん2 さんに感謝!)ので修正しました

こんな感じで RewriteRule ^(.*)$ /mtview.php [L,QSA]直前に書きました(Perl 版~の場合は mt-dynamic.php に読み替えて)。

RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jp*g|png)$ というのは、.cgi で終わる CGI ファイルや画像ファイルなど、「動的生成することが アリエナイ ファイル」ではない(!)という条件です(ややこしい)。要するに、CGI や画像ファイルは動的生成しないよ、ということ。

このブログでは真説・対spam最終兵器 CGIリネーム烈伝 : 亜細亜ノ蛾 で書いたようにコメント・トラックバック CGI をリネームしていますが、いまだにリネーム前の CGI にアクセスがあります。──その度に負荷が……。画像ファイルの指定はおまけです。その他、みなさんの方で思いつく拡張子をぶっこみングするヨロシ(何語?)。

RewriteCond %{REQUEST_URI} !^/mt/cm/.*$ の部分は、リネームしたコメント CGI の URL です。これも「動的生成しない」と指定しています。ここはみなさんの環境に合わせ、「動的生成するファイルが存在しないディレクトリ」を指定してください。

導入した結果

ということで、上記の数行を入れただけで、半日で 500 アクセス(!)釣れました。みんな、リネーム前のコメント CGI へのアクセスですた。──一体、どんだけサーバに負担かけていたんだろう……。というか、いまはみんな「404」を返していますが、なんか仕返ししたいなー。ファッ●! スパマーめ!

まぁ、それでもぜんぜん「負荷率」が減らないのが、Xrea.com クオリティ ☆

今後

さて、上の方法は .htaccess ファイルをブログのルートディレクトリに設置して「指定した条件に当てはまらなければ、動的生成を試みる」という方法ですが──

──書いているうちに、もっと賢い方法を思いつきました。

要するに、「動的生成するかどうかの条件」を書いた .htaccess はブログのルートディレクトリに置かず、動的生成したいファイルがある場所だけに設置する。

  • http://example.com/mt/

    • ブログ・ルート・ディレクトリ

    • ここの .htaccess には動的生成のルールは書かない

  • http://example.com/mt/archives/

    • ブログの記事がある場所

    • 動的生成するファイルがあるので、ここの .htaccess ファイルに動的生成のルールを書く

  • http://example.com/mt/tag/

    • タグのページがある場所

    • タグは動的生成ではなく Tagwire Plugin などでタグを生成する

    • よって、ここも動的生成のルールは不要

こんな感じ。これがベターですかね。

──こうして考えていくと、つくづく URL の設計って重要だなー。Web デザインというモノは、色や形だけではなく、URL も含めて考える必要がありますね。

この記事のタグ(偽)

[この世で最もお馬鹿な人種は?][spammer]

[2] このページの一番上へ戻る