ブログをS3 websiteからさくらVPSに移転した

このブログはTinkererを利用していて、reSTで書いたあとhtmlをsphinxで生成したものをS3で公開しています。これで基本的に落ちることもないし、なにかの拍子にアクセスが増えたりしてもS3が勝手に耐えてくれるので楽だなぁという感じで使っていました。

それが、昨年はいくつかの記事がそれなりにアクセスがあって、すごく楽しかったしありがたかったのですが、アクセスが増えて気づいたのが、S3なのでデータ転送が従量課金なので結構金がかかるっていうことです(それ自体は当然ですが、小規模の時には気にしてなかったという)。一応、Adsenseを貼っていてその収入を上回るほどではないのですが、 iPadのRetinaディスプレイをDPポートに接続して外付けディスプレイを作る記事 を公開した月は普通に$50近い課金があってドン引きでした。

転送量が多いのには単純にアクセスが増えたから意外にも理由があって、さくっと2点+αかなぁと思っています。

  • オリジナルの画像はFlickrに置いてるものの、サムネイルはS3に置いていて結構たくさん記事で表示している
  • トップページに20件以上の記事をほぼ全文表示していて、当然画像サムネイルがトップにアクセスするだけでかなりの数がロードされる
  • 実は記事のうちいくつかで、サムネイルロードしてるつもりがオリジナルのが画像を縮小させる形でロードしてた(ただのミス)

というわけで、3点目は記事自体を修正するとして、要は画像を盛大にロードしてデータ転送量に転嫁されていて自爆していたという話です。

とりあえず、トップページの記事数削減とアーカイブページの作成

トップページに記事数増やしてたのは実は アーカイブページ を調整するのがめんどくさくて20件もさかのぼれれば充分だろっていう最初にブログつくってSphinxのテーマ調整してたときのサボりが原因なだけなので、今回がんばってアーカイブページのCSS,HTMLを調整して、ページの上部とサイドバーにリンクを設置しました。それとともに、トップページの記事数を3に削減。

これで、一度表示されると、5-6MBくらい転送するっていう割とびっくりする状況から、200KBくらいまで減りました。それと一応、 アーカイブ(記事一覧)ページ を一応ちゃんと設置できたので、転送量削減よりもそっちのほうがよかったかも。

で、サムネイル表示問題をどうにかする

とはいえってところで、結局、アクセスの大半は検索経由か、どっかのSNS経由なので、トップページの転送量を削減してもたかが知れていて、依然、S3の課金がそれなりになってツライ状況です。

というわけで、結局、記事のサムネイルをロードする部分をどうにかするのがよいのだろうという結論に至るわけですが、ここで一応選択肢は2つあるかなぁという状況でした。

  1. サムネイルの置き場をそもそもS3からFlickrに変えてしまう
  2. S3 websiteをやめて、転送量課金されないところに移転する

S3の堅牢性とか性能を考えると、1のFlickrにサムネイルだけ移してしまうってのは結構有力かとおもったのですが、まず今のimageとかfigureディレクティブの記述の置換がめんどくさいっていう理由とreST的に外部のURLをimageとかにつかうと、”WARNING: nonlocal image URI found”とか言われてしまって微妙とかそういう理由でやめました。所詮個人のブログなのでお手軽さ優先でっていうことで。

で、そうすると、転送量で課金されなくて、まともに使えそうな移転先を探すことになるわけですが、実はこのブログのHTMLを生成するための環境ってさくらVPSにあって、その他ほかの用途にも使ってたり使ってなかったりしたわけですが、さくらVPSなら転送量課金もないしなーということで、ビルドしているVPSでそのまま公開できるようにしてしまうことにしました。なにかの拍子にアクセスが一気にきた場合にどうなるかは未知数ですが、まあそれでも常にすごいアクセスがあるわけでなし、去年のようにアクセスがものすごい集中してしまうことがホントにまた起こるも限らないしっていう適当な思考で。nginxで静的なHTMLや画像を提供するだけなら相当耐えるだろうというもあります。

というわけで、さくらVPS 1Gでそのままnginxでホストすることにしました。

実際の移転作業

実際の移転作業は以下のような手順で行いました。

  • さくらVPSにnginx入れる
  • Gentooなので、emerge nginxするだけ

nginxにserverの記述を追加します。vhost.dにファイル作って以下の設定を足します。

server {
  listen 80;
  server_name misc.mat2uken.net;

  access_log /var/log/nginx/misc.mat2uken.net.access_log main;
  error_log /var/log/nginx/misc.mat2uken.net.error_log debug;

  root /var/www/misc.mat2uken.net;

  location /img {
      expires 365d;
  }

  location /blog/_static {
      expires 30d;
  }

  location /blog/_images {
      expires 30d;
  }

  location / {
  }
}

とりあえず、/img, /blog/_static, /blog/_imagesはexpiresを設定しています。/imgはロゴとかなので基本的に更新はないので長めに、/blog/_static, /blog/_imagesはCSSや記事の画像が含まれるので、どれくらいのキャッシュ期間にするのか悩ましいところですが、最悪ファイル名を手動で変えることで無理矢理更新させる方向で考えて30日に設定しています。

で、この後、/var/www/misc.mat2uken.netにコンテンツを配置するわけですが、imgは作業ディレクトリから単純にシンボリックリンクを貼っています。そして、実際にtinkererで生成されたコンテンツに関しては、シンボリックリンクを張るわけでなく、rsyncで手動コピーします。

なんで手動でコピーしているのかというと、とりあえず自分で確認するように実際には別にもうひとつディレクトリを用意していて、build→確認用ディレクトリにrsync→ブラウザの確認→最終的にblogディレクトリにコピーという手順を踏んでいるからです。これはもともとs3のときはどっちにしてもアップロードという手間があったので、さくらVPS上で確認(生成されたものそのまま)→アップロードという手順でやれていたのを同じサーバ上で、確認と公開をする関係上、すこし手順を変更しました。

というわけで、やっつけrsyncスクリプト(deploy_local.sh)はこんな感じ。

while getopts d OPT
do
    case $OPT in
        "d" ) DRAFT="TRUE" ;;
    esac
done

pushd /var/www/misc.mat2uken.net
if [ "$DRAFT" = "TRUE" ]; then
    rsync -avuP /home/ku/work/misc/blog/blog/html/ __xxxxx/
else
    rsync -avuP /home/ku/work/misc/blog/blog/html/ blog/
fi
popd

これで、-dをつけて実行すればとりあえず、確認用のディレクトリにコピーされ、公開時はオプションなしで実行します。よくかんがえたら、ミスを防ぐ意味で逆がいいですね。-pで公開とかのほうがオプション付け忘れとかなくていいかも。ただ、実際にはビルドスクリプトもシェルにしている(.DS_Storeとか消してからビルドするため)ので、そこで、ビルド成功後→./deploy_local.sh -dを最後に自動的に実行するようにしています。

なので、ある程度記事を書く→./build.shを実行→ブラウザで確認用URLを叩いて確認をループさせて、最終的に、./deploh_local.shを実行して公開という流れになりました。

最後に、Route53の変更

で、最終的に、DNSを書き換えます。といっても、Route53を使っているので、Management ConsoleからS3にALIAS設定しているものをさくらVPSのIPにしてAレコードとして書き換えるだけ。

あとはのんびり待っていればそのうちアクセスはさくらVPSに切り替わります。S3側のコンテンツもとりあえず維持しておけばユーザがアクセスできない時間帯があるわけでもなし、この期間中に更新しなければ無停止と言えるでしょう。TTL60sとかにしてるので、切替→1-2時間で変わってるの確認→寝る→朝には次の記事を更新くらいの感覚で充分問題なし。

というわけで移転完了

というわけで、現時点でこのブログはさくらVPSからnginxでホストされています。転送量の従量課金は仕事で使う分にはちゃんと試算もするし、利用用途次第だけど割と誤差の範囲って思えるんだけど、個人で$50とかになるとつらいっていうのを実感したところでした。

さくらVPSで耐えられなそうな負荷が来そうならCDNに逃がすみたいなのを簡単にできたりしないもんかなぁというのを次は考えてみたいところ。