読者です 読者をやめる 読者になる 読者になる

キャッシュなんかにも対応していない古い動的なサイトを臨時で静的サイト化する

いろんな理由でサイトのアクセス数が急増してどうにか対応しないとダメなんだけど使ってるCMSや仕組み自体がそんなことに対応しておらず、さてどうするってな状況になることがしばしば。本来であればCMS自体を見なおすなりサーバ構成を見なおすなりするのが本筋なんだろうけど往々にしてそんなこと言ってる場合じゃない。まず、今の現状をどうにかしたい。

ちなみに対応するために別の何かを導入して云々とかし始めると、これまたそんな場合じゃねぇみたいな話になるのでCMSや環境には手を入れず、手元にありそうな有り物で急場を凌ぐよ、という時の話。

考え方と必要なもの

アクセスが急増してサーバが大変なことになるのは、そもそもCMSが悪いわけです。ロジックがしっかりしてさえいればいいのですし、DBなんぞに接続しに行ったり、SQLの発行なんかしちゃったりしなければなおよろしい。はっきりいえば動的に動いてくれないほうが良いわけです。流石にこそまでは言い過ぎなので、だからキャッシュなんかが使われていたりします。

とは言っても手元のCMSはボロだし古いしそんなリッチな機能はない。なので擬似的にそういった環境をでっち上げようというのが今回の考え方。

必要な物は
- mod_rewrite
- wget
- cron

使い方はwgetを使ってCMSの表示をHTML化し、mod_rewriteで切り替える。この処理をcronを使って定期的に更新する。以上。

導入手順

1.キャッシュファイルを格納するディレクトリを作成する

まずディレクトリの構成を以下のように準備する。
別にディレクトリ名はなんでもいいけど、一応ドキュメントルート以下に作ること

/real/path/to/.static_contents/caches

2.キャッシュ化したいURLの一覧を作成する

このURLの一覧はwgetに与えるのに使うので、詳しくはそちらを参照
キャッシュ化したいページのURLを一行1URLで書いていく

$ cat ./public_html/.static_contents/createCatchesUrls.txt
http://www.hogehoge.jp/
http://www.hogehoge.jp/news/
http://www.hogehoge.jp/news/494
http://www.hogehoge.jp/inquery/?type=2

3.一先ずwgetを発行してみる

前項のURLがちゃんと静的HTMLに変換されるかをチェックする。
うまくすればcachesディレクトリ配下にHTMLができるはず

$ wget -x -nH -P ./real/path/to/.static_contents/caches --restrict-file-names=windows -i createCatchesUrls.txt

4.mod_rewriteCMSと静的HTMLを切り替えてみる

静的ページに切り替えないアクセス元を指定しておく。特にwgetを発行するサーバのIPは設定しておくこと。そうしないとwgetで更新しようとしてもキャッシュにアクセスしてしまって更新できなくなってしまうため。
RewriteCond %{REMOTE_ADDR} !^123.234.123.111$

上記で作成したキャッシュディレクトリまでのパスをフルパスで記述しておく
/real/path/to/.static_contents/caches/

mod_rewriteの内容は、サーバや動いている物によって微妙に変わってくると思われるので参考までに
基本的には動いたはず。あともっとシンプルに書けそうな気がするけどようわからん。

$ cat./public_html/.htaccess

# ファイルの有効期限を追加しておく  
<IfModule mod_expires.c>  
    ExpiresActive on  
    ExpiresByType image/png "access plus 1 months"  
    ExpiresByType image/jpeg "access plus 1 months"  
    ExpiresByType image/gif "access plus 1 months"  
    ExpiresByType text/css "access plus 1 months"  
    ExpiresByType text/javascript "access plus 1 months"  
    ExpiresByType application/x-javascript "access plus 1 months"  
    ExpiresByType application/x-shockwave-flash "access plus 1 months"  
</IfModule>

<IfModule mod_rewrite.c>  
    RewriteEngine On

    # キャッシュを保存しているのは "/real/path/to/static_contents/caches/" 以下とする  
    # そのままのパスのファイルが存在する場合  
    RewriteCond %{REMOTE_ADDR} !^123.234.123.111$  
    RewriteCond /real/path/to/.static_contents/caches/%{REQUEST_URI} -f  
    RewriteRule ^(.*)$ /.static_contents/caches/$1 [L]

    # index.php、index.html、index.htmの場合、index.htmlに変換してファイルが有るかをチェック  
    #   url=のQueryStringを除外しているのはCakePHP対策  
    RewriteCond %{REMOTE_ADDR} !^123.234.123.111$  
    RewriteCond %{QUERY_STRING} !^url=([^=&]+)  
    RewriteCond %{REQUEST_URI} ^(.*)/index.(php|html|htm)  
    RewriteCond /real/path/to/.static_contents/caches/%1/index.html -f  
    RewriteRule ^(.*)$ /.static_contents/caches/%1/index.html [L]

    # Query Stringが含まれる場合の処理  
    # そのままのパスのファイルが存在する場合  
    RewriteCond %{REMOTE_ADDR} !^123.234.123.111$  
    RewriteCond /real/path/to/.static_contents/caches/%{REQUEST_URI}@%{QUERY_STRING} -f  
    RewriteRule ^(.*)$ /.static_contents/caches/$1@%{QUERY_STRING} [L]

    # Query Stringが含まれる場合の処理  
    RewriteCond %{REMOTE_ADDR} !^123.234.123.111$  
    RewriteCond %{REQUEST_URI}  ^(.*)$  
    RewriteCond %{QUERY_STRING} !^url=([^=&]+)  
    RewriteCond %{REQUEST_URI} ^(.*)/index.(php|html|htm)  
    RewriteCond /real/path/to/.static_contents/caches/%1/index.html@%{QUERY_STRING} -f  
    RewriteRule ^(.*)$ /.static_contents/caches/%1/index.html@%{QUERY_STRING} [L]

</IfModule>

5.ブラウザで様子を見てみる

ここまで上手く行けばブラウザで見た場合はwgetで作成したキャッシュファイルが表示される、はずだが上手く行けば見た目では何も変わったように見えない。それでは困るのでキャッシュファイルに微妙に手を加えて変化が確認できるようにしておこう。例えばタイトルを少し変更しておくなど。

また、いきなり本番環境で導入すると大惨事なので必ずテスト環境で確認すること。ついでにwgetをもう一回くらい発行してみてちゃんと更新できるかも合わせて確認。

6.全てうまく行けばwgetシェルスクリプト化してcronに登録

以下のスクリプトではcaches_tmpなるディレクトリを作ってコピーしたりしてるのは、無くなったファイルのキャッシュを持ち続けないため。ほんとにこんなのでいいのかぶっちゃけよくわからない。で、このスクリプトをcronに登録しておく。この辺も状況によっていろいろだと思うので適宜確認しながら導入のこと。

$ cat ./public_html/.static_contents/createCatchesUrls.sh

#!/bin/sh

mkdir  /real/path/to/caches_tmp  
wget -x -nH -P /real/path/to/caches_tmp --restrict-file-names=windows -i createCatchesUrls.txt

rm -rf /real/path/to/caches  
mv     /real/path/to/caches_tmp ./caches

$ crontab -l
*/5 * * * * /real/path/to/./public_html/.static_contents/createCatchesUrls.sh