WordPressで3000万PV/月のサイトをさくらのクラウドに構築した話


今回のサイトを含め、WordPressでのサイト構築Tipsをこちらで更新中です。
http://qiita.com/yousan/items/c925f0a241be02a55292

# はじめに
一日のPVが100万、月の3000万PVのサイトを某ブログシステムからWordPressに移行する案件がありました。

ウェブサイトの規模感を計る指標はいくつかありますが、僕の中では100万PV/月を超えてくると中規模かな、と思っています。
3000万PV/月ですとそこそこの規模感ですね。

「WordPressで大規模サイトって大丈夫なの？」と聞かれる事がありますが結構大丈夫です。

このサイトをさくらのクラウドへ移行しました。OSパッケージとしてKUSANAGIを利用しました。
KUSANAGIを使えばCentOS + nginx + php-fpm (or hhvm) 周りをそこそこの初期状態で設定してくれます。


# 現行サイトからの移行
今回はすでに某ブログシステムにサイト自体があり、そこから一般的なWordPressへ移転する、ということでした。
ですのでブログにはすでに流入があり、サイト構築段階からその数を加味する必要がありました。

# 中規模サイトの定義
ひとえに「中規模サイト」と言っても難しいですね。
個人的にCMS系では
* アクセス数
* コンテンツ数
* コンテンツ長
の三要素の大きさで計っています。これらみっつを掛けたものを数値化すれば…、というのは別のお話ですね。

特にアクセス数が最も簡単な目安で、月間に100万PVを超えると中規模だと思っています。(億の位になると超大規模かな？)
ですので今回のサイトはそこそこな規模ですね。


# 転送量
インフラの設計で大きな指標となったのは転送量でした。

通常のPHP負荷はキャッシュとスケールアウトを組み合わせれば，そこまでコストを掛けずに伸ばすことができます。ですが転送量はアクセス数に応じてグングンとコストが掛かります。(特にAWS)
移行の提案段階から携わっていたので転送量からのコスト見積もりは重要な項目でした。
また瞬間的な転送量、帯域幅についても十分考慮する必要がありました。

現行サイトではおよそ10TB/月 (300GB/日)で、且つサイトのアクセス数が右肩上がりでしたので、それに応じて増加する変動費についても考える必要がありました。

さくらのクラウドでは転送量についてはルータ、スイッチの料金プランを上げることで対処できます。
[転送量に応じたトラフィック制限はありますか?](http://cloud-news.sakura.ad.jp/faq_top/faq/#Q007)
サイトを運用していて制限がかかると怖いので営当の方に聞いた所、転送量しきい値を超えたからといって急に制限が掛かるわけではなく、警告などがありますよ、とのことでした。(もしかしたら非公式な回答かもしれません。)
また転送量の計測については利用者側自身が行う必要がある、とのことでした。
電話の応答で丁寧に答えてくれて安心でした。

今回はお客様と話合った上で「月間 16.2TB」の転送量のプランにしました。コスト的にはスモールスタートをして制限にかかったら上げる、ということもできましたが、サーバダウンを絶対に避けたいとの意向から余裕を持ったプランを選択しました。

転送量には余裕を持たせることにしましたが、CDNを組み合わせることで転送量の削減も同時に行いました。

# KUSANAGI
インスタンスのベースにはKUSANAGIを採用しました。簡単設定でキャッシュやnginx周りの設定を行ってくれるのでありがたいです。
少し前にKUSANAGI自体を試していましたので有効活用できました。

## サイトマネージャとキャッシュ
KUSANAGIでは標準でいくつかのプラグインが入っています。その中の一つにキャッシュ機能を提供するサイトマネージャ(であってるのかな？)があります。
このキャッシュ機構によりCPU負荷を下げるのですが、キャッシュが効きすぎるきらいもありました。
運用を開始してすぐに「コメントが反映されない」という指摘を受けました。
調査したところこのキャッシュ機構によりコメントが反映されなくなっていました。コードを見るとコメントにフックしてキャッシュをクリアする、という箇所がコメントアウトされていまして、コメントアウトを外したのですがうまく行きませんでした。
デフォルトの設定ではキャッシュが30分ぐらいとなっています。結局はこの値を1分にして対処することにしました。

今回構築したサイトではコメントが活発です。毎分数件のペースでコメントが付きます。ですので自分のコメントが反映されるかどうか、というのは重要な問題でした。
1分のキャッシュ時間は短すぎるのではないかという事に関しては、「そもそものアクセス数が多い」「最新の記事にアクセスが集中する」ということから十分に効果を発揮しました。
キャッシュ戦略は非常に重要ですね。

## ウェブサーバとDBサーバ
インスタンスは二つ作りました。nginx+phpとmysqlでそれぞれ分けました。
DBサーバを分けておくだけで負荷に耐えやすくなります。特にmysqlにはメモリをたくさんあげると結構早いです。そのうえ障害の切り分けも楽です。
nginx+php側はコア数を多めに、mysql側はメモリを多めにしてインスタンスを作りました。
二つともKUSANAGIでセットアップを行い、nginx+phpサーバではmysqlをオフに、mysqlサーバではnginx+phpを管理用としてphpMyAdminを入れておきました。(あとmunin）


# CloudFlareとphoton
今回のサイトへはCloudFlareを導入しました。
何気に今回のサイトでCloudFlareが一番仕事をしてくれているかもしれません。
CloudFlareはフロント側のキャッシュとして働いていて、転送量を下げてくれます。
下のグラフのオレンジの部分がキャッシュとして返答した割合です。
<img width="956" alt="Screen Shot 2016-03-21 at 11.51.07 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/47327/2e9098b0-5b91-ce7c-1387-3621d00c4a0c.png">

おおよそ75%ほどキャッシュされました。
サイトの特性にもよりますが最低でも50％、高いサイトですと90%ぐらいのヒット率を目指します。この辺りは加減が難しいので運用しながら調整していくことになります。

またJetpackに付いてくるphotonプラグインも利用しました。こちらは画像系のCDNです。

この二つを組み合わせることで奥側のサーバへ届くリクエストは転送量ベースで (20GB/日 = 500GB/月)となりました。
(ただし安全のため転送量プランは大きなものになっています。将来的には変更になるかもしれません)

photonは非常に有効なのですが利用上の注意があります。
現在はキャッシュされた画像を自前でコントロールできないようで、キャッシュ画像の削除は個別にサポートへ連絡するしかありません。
大規模なサイト運営ですとキャッシュされた画像へ著作権侵害の申し立てを行われる事があり、その際に対処することが難しいです。
その辺りは導入の際に注意することが必要です。

# 負荷試験
さくらのクラウドでインスタンスを横に作成し、[Gatling](https://qiita.com/tags/Gatling/items)にて負荷試験を行いました。
キャッシュ無しで想定しているアクセス数の負荷を掛けましたがアッサリ落ちました。
これについては全然解決しなくて、「ぶっちゃけやっぱりWordPressって重いな」って思いました。
(とはいえ、WordPressは適切にキャッシュを行えば十分耐えうるシステムです。)

`想定アクセス = サイト見込みPV * CloudFlareのキャッシュ通過 * KUSANAGIのキャッシュ通過`

ということで、キャッシュを通り抜けてくるアクセス数が上がるとなんだかんだで結構耐えきれません。
今回のケースではコンテンツの内容的にキャッシュのヒット率をできるだけ上げるようにして対応しました。
WordPressでスケールアウトさせているケースというのはあまり見聞きしませんが、今以上のアクセスを捌くのであればスケールアウトさせる必要があります。
今回はスケールアウトしませんでしたがエンジニア的にはそういった案件に関わって行きたいですね。


# まとめと感想
## インフラを担当して
インフラ担当を担当する上ではあたりまえですが、移行に伴ってサーバのダウンタイム、アクセス不可を最小となるようにしました。DNS切り替えでしたのでエンドユーザは全く意識することなく切り替えが完了したと思います。
今回のアクセス規模は僕の担当した中でも最も大規模でしたのでかなり神経を使いました。実際に移行するまでに負荷試験を行ったりしました。
またこれはビジネス上みっともない話かもしれませんが、問題発生時にはすぐに元のサーバに戻せるようにと心血を注ぎました。
お客様、お客様との折衝を担当してくださった会社さんともに非常に優しい方で助かりました。特に予算については余裕がありましたので事前準備なども捗りました。

## キャッシュは大変
Gatlingで過負荷試験をしたところ落ちました。これについてはキャッシュを駆使することで対処しました。

## KUSANAGIありがとう
KUSANAGIのおかげで色々と捗りました。今後もどんどんと使っていくと思います。
ただKUSANAGIってどうやって収益化してるのかなーと不思議に思いました。

## プログラミングの知識は必須
プラグインなどに不具合があった場合には内容を確認しましたし、コア側に問題があればそこも見ていきます。
WordPressへ移行ということでこの辺りで躓いてしまうと「やっぱりWordPress使えねー」となってしまって悲しくなるので持てる力を振り絞りました。