My365の作り方 〜サーバ編〜

レンタルサーバが大好きなので、わざわざサーバを自分でどうこうしようとは思わないのですが、My365はサーバがネックになってサービスが正常に動かないということは避けたいと思い、今回はVPSを選択しました。
リリースまでとそこから2週間のサーバ環境の変化と失敗の記録です。Amazonへの移行から @takus 先生に加わってもらって、一人でやっていた時より安定したサーバ環境になりました。
(よかったらこちらもどうぞ → iOS編, iOS編, サーバサイドプログラム編 )

サーバ環境

ストレージサーバ: Amazon S3
WEBサーバ&データベースサーバ&etc: さくらVPS 8GB

写真だけはS3に置いて、あとは全て1台のマシンに載せてしまう作戦です。
写真をS3に置くことにしたのは、面倒なことを考えたくなかったからです。自分で管理するより明らかに安全で、容量が増えても問題なく、WEBサーバの代わりにアクセスもさばいてくれる・・・ということで、自分でストレージサーバを用意するということは考えませんでした。
WEBサーバに、VPSを選択した理由は単に料金が安かったからです。メモリ8GBのサーバをAmazon EC2で借りると月額23,000円くらいになります。これに加えて転送料でも課金されるので一体いくらになるか想像できません。それに比べてさくらVPSなら8,000円で借りられる・・・ということで、こういう判断となりました。

さくらVPS 8GBについて

CPU: 仮想4Core
メモリ: 8GB
ストレージ: 240GB
初期費用: 19,980円
月額: 7,980円

初回で2か月分請求されるので、35,940円という連絡が来ました。ロリポップ11年分です・・・。

4日目で限界を迎える

4GBのプランにするか8GBのプランにするかずいぶん悩んだ挙句、思い切って契約した8GBのプランでしたが、あっさり悲鳴をあげはじめました。嬉しい悲鳴ですが。

(※一応補足しておくと、決してさくらVPSが非力なわけではありません。)
リリースから日に日に負荷が増えていって4日目にはロードアベレージが4を超えて、このままじゃ明日は乗りきれないかも・・・という状態になりました。
多くのWebサービスは夜にアクセスが集中すると思いますが、My365も同様です。一日を振り返って写真を投稿する人が多いようで、21時から24時の間に急激に負荷が増えます。特に写真投稿は画像の縮小・圧縮処理を伴うので、辛いものがあります。

画像処理部分を分離

実は8GBのVPSの他に、MySQLのレプリケーションのスレーブとして512MBのVPSを借りていました。スレーブと言っても、参照されているわけではなく、ただバックアップ用に使われていたものです。
そこで、画像処理の部分だけを、このVPSに分離することにしました。My365は投稿された写真を非圧縮の状態でもAmazon S3に保存しています。その後縮小したり圧縮したりして、それもS3に保存しています。
そこで、非圧縮の状態でS3にアップロードしたあとは、画像サーバに任せるという分離をしました。

// 画像の圧縮を別サーバで行う
$data = http_build_query(array('name' => $name), "", "&");
$header = array(
		"Content-Type: application/x-www-form-urlencoded",
		"Content-Length: " . strlen($data)
);
$context = array("http" => array(
			"method" => "POST",
			"header" => implode("\r\n", $header),
			"content" => $data
	));
$json = file_get_contents(URL_IMAGICK_SERVER, false, stream_context_create($context));
// 失敗した場合は自サーバで行う
if (!$json || !json_decode($json))
	if (!$this->Compress($name))
		return false;

画像処理サーバ側で一度S3から非圧縮の画像をダウンロードしなければならないので時間的にオーバヘッドがありますが、負荷が高まって極端にCPU待ち時間が長くなるよりはマシです。
サーバを2台体制にして、画像処理サーバがクラッシュした場合に写真の投稿が全くできなくなるというのは困るので、画像処理サーバから応答が無かったり失敗の応答が返ってきた時にはメインサーバの方で処理するというようにしています。
他にもMySQLやApacheの設定を調整したり、WEBビューの画像を全てS3に丸投げするなどしました。この効果が出たのか、5日目以降ひとまずアクセスをさばけるようになりました。

2週間でAmazonに移行

その後1日あたりのダウンロード数は少し減り、新規の流入は減ったのですが、幸いユーザーの皆さんは継続的に利用していただいているようで、アクセスと負荷は右肩上がりになりました。さすがにWebサーバも分散したくなってきて、Amazonに移行することにしました。
このあたりでさすがに一人でやるのは無理と判断して、新たに @takus に参加してもらうことにしました。現在の環境を全て構築してくれたのは彼なので、詳しくは彼がブログに書いてくれるはずです。(プレッシャー)
Amazonへの移行は11/9に行いました。4時〜6時の一番アクセスの少ない時間にサーバを完全に止めて移行しようと考えていました。やることは以下で、10分か20分止めれば済むだろうと(勝手に)思っていました。

  1. さくらVPSのWEBサーバを止める
  2. データベースをダンプする
  3. Amazonサーバにデータベースを読み込ませる
  4. DNSをAmazonのロードバランサに向ける
  5. さくらのサーバへのアクセスをリバースプロキシでAmazonに飛ばすようにする

ELBの罠にハマる

DNSをAmazon ELBに向けようとしたところ、www.my365.in には、CNAMEレコードで lb-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com を設定できるものの、my365.in には設定できずにハマりました。
常識ですか?・・・全然知りませんでした。
ちょっと調べたらすぐ出てきました。 Amazon ELBでホスト名なしのhttp://example.comを運用すると発生するいくつかの弊害 のようなブログがぞろぞろと・・・。
アプリが叩くAPIのURLはhttp://my365.in/で固定されてしまっているし、「解決策はない」みたいなブログもたくさん出てくるし・・・。「ロードバランサのIPを直接Aレコードに書いちゃうか?でも、2週間に1回くらいはIPが変わるらしい・・・。」などと絶望していました。
Amazon Route 53+ELBでホスト名なし(zone apex)の運用もOKになったので試してみた
そんな時に、このブログを発見。今年の5月に正式リリースされたRoute 53というAmazonのDNSを使えばいけるらしい!ちゃんと対応してくれるAmazonさんと、このブログを書かれたhirose31さんに「ありがとうございます!」と叫びます。

まだハマる

my365.inのネームサーバをRoute 53に変えるようにムームードメインで登録して、さくらのサーバのリバースプロキシを設定して、リリースです。
・・・と思ったらどうもうまく動いておらず、自宅の無線LANだとEC2までリクエストが届くのに、e-mobile経由だと届かない、という状況に陥ります。DNSのキャッシュのふるまいって難しいですね。
これを解決するのに3時間ほどかかってしまい、めざましテレビは終わるし、TwitterなどでもMy365落ちてるという報告がどんどん来るし、申し訳ない気持ちでいっぱいになりながら、意識失いかけの状態でパソコンたたきまくってました。
この間にアクセスしてくれた方にはご迷惑おかけしました。サーバ負荷が日増しに増えていて焦っていましたが、もう少し事前準備をしっかりしておくべきだったと反省しました。

おわりに

そういうわけで、現在は以前のさくらVPS8GBのところが3台構成になりました。

ストレージサーバ: Amazon S3
データベースサーバ: Amazon EC2 ラージインスタンス
WEBサーバ: Amazon EC2 ハイCPUミディアムインスタンス×2

止めてはいけないという責任感みたいなのに潰されそうですが、サーバももっと快適で高速なレスポンスを返せるように先生と相談しながら改善していきたいと思います。

コメント

  1. […] 投稿ナビゲーション ← 前へ 次へ → […]

  2. editnuki より:

    画像みたいにリクエストされるものがわかっているならmod_cache系を利用するとphpとかmysqlとかにアクセスなしでリクエストを返すこともできるので高速化が可能かもです。
    AWSであれば、コントロールパネル上でロードバランサが利用できる(有料?)はずなのでリバースプロキシをあえて使わず分散処理させるとかも可能かと。
    S3への接続方法がわかっていませんが、S3を単純にマウントしている場合は正常にマウントできているか、WEBサーバからDBサーバへの接続ができるかの監視はした方がいいと思います。
    (半年くらい前に頻繁にS3のマウントが勝手に外れるという事象がありました。最近は知りませんが・・・)

  3. […] Previous: My365の作り方 〜サーバ編〜 Next: 落ちないiPhoneアプリが作りたい自分のための、メモリ不足でアプリが強制終了する話。 […]

タイトルとURLをコピーしました