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

彼女からは、おいちゃんと呼ばれています

ウェブ技術や日々考えたことなどを綴っていきます

オシャレエロサイトをリリースして、10万PV/日を捌くためにやったこと

Linux Rails

前回のエントリー「Rails3 と jQuery で、真面目にオシャレなエロサイトをつくってみました」で紹介したオシャレエロサイト。

おかげさまで大変な反響がありまして、リリース2日目には1日のアクセスが10万PVを超えました。

しかしその裏では、どっと押し寄せたアクセスを捌くために、画像ファイルを別サーバに移したり、最終的には AWS の CDN である「Amazon CloudFront」を導入したりと、なかなか大変でした。

ここでは、リリース前にどう準備していたかと、リリース後に何が起こったか。そして、どう判断し、どう対策を取ったか。それらを書き留めておきます。よろしければ参考にしてください。

オシャレエロサイトをリリースして、10万PV/日を捌くためにやったこと

  1. リリース前の構成(メモリ1GB のサーバ1台)
  2. リリース前に行った負荷テスト
    • (1) 1秒間に何アクセス捌けるか?
    • (2) 1日何アクセスを超えたあたりからレスポンスが重くなりはじめるか?
  3. ゆーすけべー日記をみて、12万PV/日をひとつの基準にした
  4. リリース後 - load average は 1.0 以下だけど、ネットワークトラフィックがヤバい
  5. 画像ファイルを別サーバに移す(メモリ1GBのサーバ2台構成)
  6. 画像ファイルを Amazon CloudFront(CDN)に移す(メモリ1GBのサーバ1台 + CDN)
  7. 教訓 - 画像も含めた総合的な負荷テストが必要

1. リリース前の構成(メモリ1GB のサーバ1台)

最初にサーバ構成について触れておくと SaaSes の「Osukini Cloud」というクラウドホスティングサービスを利用しています。

月額1,000円で 1仮想CPU(2.66GHz だったかな?)、メモリ1GB。さらに、金額を上乗せすると CPU とメモリを増強できるのがこのサービスの良いところなのですが、残念なことに、新規申込は既に終了しているようです。

基本的に上記サーバ1台に ApacheRailsMySQL も載せて稼働させていましたが、後述のとおり、リリース後に構成を少し変えました。

2. リリース前に行った負荷テスト

とりあえず動くものができた段階と、サーバのチューニングを行ったときと、リリース直前に、負荷テストを行いました。負荷テストを行えば、

  • レスポンス速度はどのくらいか?
  • どのくらいの負荷がかかったときに遅くなりはじめるか?

等を把握することができ、それらがいろいろな判断の材料になってくれます。テストの結果によってはサーバ構成等を変える必要も出てくるので、できるだけ早い段階で行うのが吉です。

負荷テストを行うことができるツールにもいろいろあるのですが、僕は導入と操作が簡単な ab(Apache Bench)と httperf というツールを使って

  • だいたい 1秒間に20アクセス捌ける(ab)
  • だいたい 1日10万アクセスを超えたあたりからレスポンスが重くなりはじめる(httperf)

ことが確認できたので、1日10万アクセスに近づいたら、サーバの CPU とメモリを増強しようと考えていました(負荷テストツールの導入方法や使い方は下記サイトを参照してください)

(1) 1秒間に何アクセス捌けるか?

1秒間に捌けるアクセス数を調べるには、ab が一番手っ取り早いです。-c オプションで同時接続数、-n オプションでトータルどれだけのリクエストを投げるかを指定します。

$ ab -c 10 -n 100 http://example.com/

負荷テストが終了したら、結果の中に

Requests per second: 18.12 [#/sec] (mean)

という数字があると思いますので、それが1秒間に捌けるアクセス数です。

といってもあくまでこれは理論値で、実際に1秒間に18アクセスも捌ける訳ではないのですが、サーバのチューニングをする際に、ビフォーアフターの基準値として使われることが多いようです。僕もこの値を見ながら Apache のチューニングを行いました。

(2) 1日何アクセスを超えたあたりからレスポンスが重くなりはじめるか?

レスポンスが重い軽いについては top コマンドで確認できる「load average」を基準にし、

レスポンスが重くなりはじめるとき = load average が 1 を超えはじめるとき

と仮定しました。

そして、httperf は、--rate オプションで、1秒間に何リクエスト投げるかを指定できるので、1秒間に1リクエストの割合で10分間負荷をかけ、次に1秒間に2リクエストの割合で10分間...とどんどん負荷を高くしていって、5分間の load average を記録していきました。

$ httperf --server example.com --uri / --rate 1 --num-conns 600 --num-calls 1
1秒間あたりのリクエスト数 5分間の load average
1 0.18
2 1.13
3 1.52
5 2.04

これをみると、1秒間に2リクエストくらいまでなら大丈夫で、それを超えると次第に重くなるということが分かります。ただ、1秒間に2リクエストってどのくらいのものなのかよく分からないので、これを1日あたりのアクセス数に換算する必要があります。

その換算にはきちんとした公式があるわけではなくて、本ブログの時間帯別アクセス分布を参考にしました。

上記は本ブログの5万アクセスの時間帯分布を表したものですが、最も多い22時台でおよそ3,500アクセス。これを計算しやすいように3,600アクセスだとすると、

1日5万アクセス >> 1時間に最多で3,600アクセス >> 1秒間に1アクセス
1秒間に2アクセス大丈夫 >> 1時間に7,200アクセス大丈夫 >> 1日10万アクセス大丈夫

ということになって、1日10万アクセスくらい大丈夫だよねという結論に至りました

3. ゆーすけべー日記をみて、12万PV/日をひとつの基準にした

1日10万アクセスくらいまで大丈夫だとして、それでリリースして問題ないのか否か。実際に自分のサイトにどのくらいのアクセスが来るかなんて、リリースしてみるまで分かりませんが、

自分はこういうサービスをリリースした。このくらいのアクセスが来た

というような情報は探せば案外見つかるもので、僕の場合はゆーすけべーさん(@)のブログが参考になりました。

1月6日には動ナビという日本最大の裏ポータルサイトにも取り上げられ、ピーク時にはサイト内合計で 12万PV / 1day

1日12万PVも10万PVも似たようなものかなと楽観視して、それならサーバ構成変えなくてもまあ大丈夫かな、と(後述のとおり、全然大丈夫じゃなかったんですけどね)

4. リリース後 - load average は 1.0 以下だけど、ネットワークトラフィックがヤバい

3月31日(土)の夜にリリースしました。土曜日にリリースしたのは、何か問題があっても日曜日に対応できるように、という考えからでした。

リリース直後から、top コマンドで load average 見たりとか、free コマンドでメモリの使用量を見たりとかしていました。あと munin のグラフをぼーっと眺めていたり。

そうこうしているうちに紹介記事(本ブログ)にはてブが付きはじめて、それと並行してサイトにもアクセスが集まってきました。

気づけばサイトがだんだん重くなってきて、画像がところどころ表示されなくなって、これはヤバい。

(後から調べたところでは、1時間3,000PVを超えたあたりからだんだん重くなってきていました)

相変わらずバカのひとつ覚えみたいに load average を監視していて、まだ 1.0 以下の値だったので「あれ?なんでだろ?」なんて思ってましたが、さすがに「あー!ネットワークかー!」と気づいて、netstat コマンド叩きました。

$ netstat -s

TCP の「failed connection attempts(接続失敗数)」がみるみる上がっていくのを見て、こいつぁヤベエな、と(でも、正直、ここのところはイマイチよく分かってないです。これから勉強しようと思います)

5. 画像ファイルを別サーバに移す(メモリ1GBのサーバ2台構成)

ネットワークトラフィックがヤバいと気づいたので、まずは画像ファイルを別サーバに移そうと考えました。

幸い、開発環境用に、本番環境と同様のサーバを1台借りていたので、画像の参照 URL をそちらに向けて急場を凌ごうと。

こういうときに Rails 3.1 から導入された Asset Pipeline は便利ですね。設定ファイルに

config.action_controller.asset_host = "http://assets.h.300x.info"

と一行書き足してあげるだけで事が済んでしまいます。

画像ファイル(正確には、JavaScriptCSS も)を別サーバに移して、メモリ1GBのサーバ2台構成になりました。多少もっさり感が残るものの、正常に表示されるようになりました。

6. 画像ファイルを Amazon CloudFront(CDN)に移す(メモリ1GBのサーバ1台 + CDN)

そんなこんなで、リリース当日は画像を別サーバに移し終えた段階で床に就いたのですが、布団の中で

やっぱりあのもっさり感はいかんのではないか?

と思いまして。

多少費用がかかってもサクサク動くようにしたい。しよう。こういうことに富豪的に対応できるようにしたのも、90日間限定にした理由のひとつなんだし。

というわけで、リリース翌日に、サクサク動作作戦決行。

やり方として、回線が太い専用サーバに移行するという手もあったのですが、アダルトコンテンツ OK で条件に見合うサーバを探すのには時間がかかりそうだったので、AWS の CDN である「Amazon CloudFront」を利用する事に決めました。

ちなみに、CDN というのは Contents Delivery Network の略で、画像や音楽や動画などのファイルサイズが大きなコンテンツを配信することに最適化されたネットワークのことです。回線がめっちゃ太いらしい。

CDN といえば Akamai(アカマイ)が有名ですが、コストパフォーマンスの面では AWS の S3 と連携した CloudFront がイイらしいという評判を聞いていたので、CloudFront を選びました。

導入の方法については下記サイトが詳しいですが、特にハマることになく3時間くらいで作業が終わりました(うち2時間はファイルのアップロード)

Amazon CloudFront に関するその他の参考サイトは、ページ下部にまとめました)

で、画像を CloudFront に移し終えたら、レスポンスが速いのなんの。リリース2日目には前述のとおり10万PV/日あったのですが、まったく問題なくレスポンスがすぐに返ってきて感動しました。

7. 教訓 - 画像も含めた総合的な負荷テストが必要

今回得られた教訓として、画像が多めのサイトであれば、画像も含めた総合的な負荷テストが必要だということです。

リリース前に利用した ab や httperf はリクエストを投げてメインの html が返ってくるまでしか扱わず、そこに画像が使われていても画像を取りにはいきません。

しかし、画像が多めのサイトではネットワークトラフィックボトルネックになることが多いようなので、そのあたりを調べるには画像も取りにいってくれる負荷テストツールを使う必要があります。

画像も取りにいってくれる高機能な負荷テストツールとしては「Apache JMeter」が定番ですが、「Load Impact」という、毎月5回までは無料で使える Web サービスもあります(最近知りました)

あと、リクエストを連続で投げたりとかはできませんが、何にどれだけの時間がかかっているのかを調べるには Firebug が一番わかりやすいかもしれませんね。

以上です。どなたかの参考になれば幸いです。ではでは。