できる!ソーシャルアプリ (1) 企画・設計段階「夢の中で思いついた、ような……」
こんにちは、ちなつです。
本日は、”歌って踊れるインフラエンジニア兼、PHPもRubyもJavaも書くPerl使い”である仲山氏の記事をご紹介します。
クラウド環境でのソーシャルアプリ企画~リリースまでのTips連載、どうぞお楽しみに!
(*本記事の最後に仲山氏のプロフィールを掲載しています)
*********************************************************************
はじめまして、株式会社エクストーンの仲山です。
今回、ニフティクラウドユーザブログに参加する機会をいただきましたので、ソーシャルアプリを公開、運用するまでを連載記事として書いていきたいと思います。
全体の流れ
この連載記事では、これまでに弊社がソーシャルアプリをリリースしてきた経験を踏まえ、クラウド環境とのつきあい方や、失敗から得た経験、TIPSなどをご紹介します。なお、具体的なソーシャルアプリの企画や実装の方法については触れませんが、 詳しい書籍がたくさんありますので、そちらをご覧ください。
今のところ以下の4回に分けての掲載を予定しています。
- 第1回: 企画・設計段階 (今回)
- 第2回: アプリの開発と負荷試験
- 第3回: リリースに向けた本番環境の準備
- 第4回: リリース後の運用
第1回は企画・設計段階と位置付け、ソーシャルアプリの特徴を簡単にご紹介し、一般的なサーバー構成とそのコスト試算を行います。
ソーシャルアプリの特徴
まず最初に、ソーシャルアプリの特徴をかんたんにご紹介します。
■ 利用者数の傾向
ソーシャルアプリの最大の特徴は、その利用者の増加傾向にあります。
通常のアプリであれば、広告や雑誌記事などによって利用者への露出を行ったタイミングで利用者が集中的に増加します。そのため、どれだけ大規模な広告を打つかなどによって、利用者数の増加をコントロールすることができます。
対してソーシャルアプリでは、似たような内容に見えるアプリが数多く存在することもあり、後出しの広告にそれほど大きな効果がありません。その代わり、リリース直後に掲載される「新着アプリ」ページに大きな広告効果があり、その時点で人気が出れば、利用者がその友達をアプリに招待することにより、一気に利用者が増加します。また、アプリの内容に満足することができなければ、一度離れてしまった利用者を呼び戻すことが難しくなります。
■ ソーシャルアプリの提供形態
ソーシャルアプリの提供形態には大きく分けて2種類があり、サーバーへのアクセス方法がそれぞれ異なります。
・JavaScriptアプリ
携帯向けアプリでは利用することができず、PC向けおよびスマートフォン向けアプリでこの形態が取られます。
SNSのサイト上にIFRAME(インラインフレーム)経由でアプリ開発者が登録したHTML(Gadget XML)が表示され、そこから呼び出されたJavaScript上でアプリを実装します。また、利用者に対するユーザインターフェースは開発がしやすいFlashを利用し、その裏側でJavaScriptを呼び出している場合が多いようです。
JavaScriptは利用者のブラウザ上で実行されますが、アプリ上での利用者の動作に応じて、データの取得や、保存が必要になった時点で、 SNS側サーバーを経由して、アプリのWebサーバーに対して都度リクエストを行います。利用者の操作はJavaScriptが一旦受け取るため、連続して行われた複数の操作をまとめてサーバーに送信する、などのアクセス軽減策が可能となります。
また、プロフィール情報などSNS側の情報を引き出すAPIは、原則としてJavaScriptのAPIとしてブラウザ上からSNS側サーバーに対して呼び出します。
・HTMLアプリ
通常のWebサイトと同様に、ページ遷移ごとにサーバー上でページを生成します。
利用者の認証についてはSNS側で行うため、 SNSサイトのサーバーが携帯端末の代わりにアプリのサーバーにアクセスし、表示内容のHTMLを取得します。このHTMLにSNSサイトのヘッダやフッタ、広告などを付与して携帯端末に返します。
また、プロフィール情報などSNS側の情報を引き出すAPIは、 RESTful APIとしてアプリのサーバーからSNS側サーバーに対して呼び出します。
既にGadget XMLやJavaScriptにより画面が表示されているJavaScriptアプリと異なり、アプリのサーバーがHTMLを返さなければ何も表示できなくなってしまうため、タイムアウトに対して厳しいペナルティが適用されます。タイムアウトが頻発した場合に、アプリに対して掲載停止や、新規利用者の受付停止などのペナルティが科されます。機会損失を避けるためには、表示時間をアプリ側でコントロールし、 SNS側のタイムアウト時間を超える前に、アプリ側で自前のタイムアウトページを表示するなどの対応が必要となります。
なお、PC向けアプリの例外として、ブラウザ三国志などIFRAME等を利用して通常のHTMLアプリとして実装されたソーシャルアプリも存在します。これらはブラウザ側からIFRAME直接アプリ側のサーバーで提供するHTMLを表示するため、上記のタイムアウト制限は適用されません。
■ アプリの動作
特に携帯向けアプリで顕著なソーシャルアプリの特徴として、通常のウェブサイトに比べて大幅にPVが多い点があげられます。
ゲーム内での「成長」や「攻撃」などの利用者の行動ごとに連続して画面遷移を行うため、回線状況次第で一人の利用者から毎秒1PV以上のアクセスが発生する場合があります。また、JavaScriptやFlashで提供されるアプリにおいても、アプリの作り方次第で、マウスクリックの連打がそのままサーバーへのアクセスとなります。
さらに、利用者毎の「持ち回数」を消費することで行動を行うパターンが一般的で、利用者が行動を行う度に、(1)その持ち回数を確認し、(2)持ち回数があれば減らし、 (3)残り持ち回数を表示する、というデータの取得・更新が発生します。そのため、データの不整合が起きないよう、 DBのレプリケーションや、メモリキャッシュを利用するのであれば特に注意が必要です。
また、アプリ利用者からの問い合わせを受けたときに追跡調査ができるよう、ユーザの行動をある程度記録する必要もあります。
このように、特にDBに対して厳しいという点がソーシャルアプリの特徴です。
企画・設計段階
このようなソーシャルアプリの特徴を踏まえて、実際にアプリの企画・設計を行っていきます。
この段階でサーバーに関する事項として、以下のようなことを検討しておく必要があります。
・企画としてのゴール
・サーバー構成と性能目標の検討
・サーバー費用の試算
・ヒットしすぎた場合の対策
・ヒットしなかった場合の対策
企画としてのゴール
企画段階で、まずは目標とする想定アクセス量をざっくりと算出します。この想定アクセス量を元に、用意すべきサーバー数を算出します。
アプリに対する平均1日PVと、どれぐらいピーク時にアクセスが偏るかを示すピーク係数の2つがパラメータとなります。今回は、ソーシャルアプリがヒットしたとされる1日300万PV(月間9000万PV)というのを目標とし、時間を絞ったキャンペーンなどによる短時間へのアクセス集中は想定しないものとします。
項目 | 想定量 | 備考 |
---|---|---|
平均1日PV | 300万PV | 事業計画で目標とする1日PV |
ピーク係数 | 2.0 | ピーク時にアクセス頻度がどれだけ伸びるかの仮定 アプリの内容や想定利用者層に応じて変更します。 今回は時間帯によるアクセス増減のみ考慮して2.0としました。 |
平均秒間PV | 毎秒34.7PV | 平均1日PV ÷ (24時間×60分×60秒) |
ピーク秒間PV | 毎秒69.4PV | 平均秒間PV × ピーク係数 |
したがって、ピーク秒間PVである「毎秒69.4PV」というアクセス量が、安定して提供すべき目標値となります。
サーバー構成と性能目標の検討
次に、アプリの企画内容から、それを実現するためのサーバー構成を検討します。
今回の連載で扱うアプリのサーバー構成を以下のように決めました。
なお、mixi等のSNS側サーバーについてはこの図では触れていません。
また、この時点でそれぞれのサーバーの性能に対するアプリの性能目標を仮置きします。
アプリを実装する前の推測は難しいが大丈夫か、と心配する方も居ると思いますが、この時点ではあくまで試算段階ですので、他の案件での事例を参考に仮置きした目標値で大丈夫、問題ありません。また、この性能目標の「精度」が開発会社としてのノウハウの一つと言えます。
サーバー | 用途 | 性能目標 |
---|---|---|
Load Balancer | アプリへのアクセスを一番手前で受け取り、各Webサーバーにアクセスを振り分けるリバースプロキシサーバーです。 今後、モバイルアプリに対する際には、タイムアウト処理も行います。 Apacheやnginx、Poundなどが広く使われていますが、今回はnginxを利用します。 | 今回の規模ではCPU1コア/メモリ1GB |
Web (Static) | 画像ファイルやスタイルシートなど、静的なファイルを配信するためのWebサーバーです。 nginxやlighttpd、Apacheなどが広く使われていますが、今回はApacheを利用します。 また、静的ファイルの送信処理は極めて負荷が低いため、実際のサーバーとしてはLoad Balancerと同じ1台のサーバー上に集約します。 | |
Web (App) | 利用者の行動に応じて処理を行い表示内容を生成する、実際のアプリ本体のプログラムが動作するWebサーバーです。 実際の開発言語にあわせて選択されます。今回はApacheを利用します。 | CPU1コア/メモリ2GBで毎秒10PV ページ本体のみ処理するため、PV=リクエスト数 |
Web (管理) | アプリ開発者が操作するためのWebサーバーです。 アプリのデータの更新や、ユーザ問い合わせ対応のための調査を行うための管理画面等や、 利用状況把握のための集計バッチ処理等を設置します。 また、各サーバーの監視や、DBのバックアップなどもこのサーバー上で行います。 | 今回の規模ではCPU1コア/メモリ1GB |
DB Master | アプリの情報を格納するマスタDBサーバーです。 後述するレプリケーション遅延によるデータ不整合のリスクがあるため、 当面はアプリ本体からはこのマスタDBサーバーのみを利用します。 |
今回の規模ではCPU4コア/メモリ16GB |
DB Slave | DBの内容をレプリケーションで複製したスレーブDBサーバーです。 集計やバックアップなど、アプリの動作に影響を与えるような処理に、 このスレーブDBサーバーを利用します。 |
今回の規模ではCPU1コア/メモリ1GB |
Cache | マスタDBサーバーへのリクエスト数を減らすために設置するキャッシュサーバーです。 プロセス再起動で記録内容が消えるオンメモリのキャッシュと、ディスクに記録内容を保存するキャッシュがありますが、 今回は前者のmemcachedを利用します。 | 今回の規模ではCPU1コア/メモリ1GB |
アプリへのアクセスが大幅に増えた場合は、マスタDBの分割やKVSの導入なども考慮する必要がありますが、まずはリリース時点での想定ということで、ごくごく基本的な構成としています。
サーバー費用の試算
それでは、ここまでの情報を元に、実際のコスト試算を実施します。
サーバー | インスタンス種別 | 台数 | 単価 | 合計 |
---|---|---|---|---|
Load Balancer / Web (Static) | Small | 1 | 13,335円 | 13,335円 |
Web (App) | Small2 | 7 | 18,144円 | 127,008円 |
Web (管理) | Small | 1 | 13,335円 | 13,335円 |
DB Master | Large16 | 1 | 91,927円 | 91,927円 |
DB Slave | Small | 1 | 13,335円 | 13,335円 |
Cache | Small | 1 | 13,335円 | 13,335円 |
総計 | 272,275円 |
ここで、Web (App)についてはインスタンスの種別によっていくつかの選択肢がありますが、以下のように最も安いプランとしています。
利用インスタンス | 1台あたり性能 | 必要台数 | 単価 | 合計 |
---|---|---|---|---|
Small2 | 毎秒10PV | 7台 | 18,144円 | 127,008円 |
Medium4 | 毎秒20PV | 4台 | 35,070円 | 140,280円 |
Large8 | 毎秒40PV | 2台 | 66,528円 | 133,056円 |
ただし、台数が増えることで運用コストも増加しますし、サーバースペックに応じて単純なかけ算で性能を予想しています。したがって、あくまでこの時点でのサーバー構成は試算のためのものに過ぎず、最終的にベストとなる構成はリリース前に実際のアプリを用いて計測して探ることになります。
アプリがヒットしすぎた場合の対策
アプリが想定を超えてヒットした場合に、サーバー環境としてどのように対策を取るかをあらかじめ検討しておき、「どうにもできない」という状況が発生しないようにすることが重要です。
■ Load Balancer / Web (Static)
このサーバーがボトルネックとなる場合には、静的ファイルを別ドメインとし、サーバーを完全に分離することで対策が可能です。また、それでも1台で足りなくなってしまう場合には、 ロードバランサー機能や、 DNS ラウンドロビンにて分散が可能です。
■ Web (App) と Web (管理)
Webサーバーについては、基本的にアクセス増加に合わせてサーバー台数を増やすことで対策を行います。
あらかじめ設定済みのWebサーバーからカスタマイズイメージを保存しておくことで、イメージ作成後に更新されたファイルのみを追加するだけで、すぐにサーバー追加が可能になります。また、各種ミドルウェアの構成の統一については、ChefやPuppetと言った構成管理ツールの利用が有効です。これについては、連載後半にて触れます。
■ DB Master
今回の構成では、既にニフティクラウドで可能な限り上位のサーバーを利用しているため、これ以上のスケールアップができません。そこで、アプリの実装に踏み込んでいくつかの対策を行う必要があります。
・DBクエリ内容の調査
一定時間以上を要したクエリを記録するスロークエリログ機能はどのRDBMSにもありますが、これを有効にしてしまうと、DBサーバー全体の負荷が上がってしまい、本末転倒となってしまいます。
そこで、Maatkitに含まれるmk-query-digestの登場です。 tcpdumpによるネットワークレベルでのパケットキャプチャ結果を読むことができます。クラウド環境であればサーバーの追加はすぐにできますので、サーバーの追加で負荷を下げたWebサーバー側でパケットキャプチャを行い、クエリ全体の分析内容をアプリ開発者にフィードバックすることができます。
・スレーブサーバーの追加
リリース時の構成では、DB Slaveはあくまで集計やバックアップ等のみに利用し、アプリ本体では利用しないこととしています。 DB Slaveサーバーをそのままアプリ本体からも利用すると、集計やバックアップによりロックが発生し、処理が滞る危険があるため、新規にスレーブサーバーを追加し、アプリ本体からの読み込みをそちらに回す事が可能です。
レプリケーションを利用する上で、遅延が発生するという点に注意を払う必要があります。特に携帯向けのソーシャルアプリでは、一人の利用者が1秒以内に繰り返しページを更新するような場合が多く存在します。レプリケーション遅延を考慮しないと、スレーブサーバー上の古い値を元に更新を行ってしまうと、負荷が多く遅延がある時間帯に、正しくデータが反映されないといった不具合が発生します。楽観的ロック(Versionパターン)等によりレプリケーション遅延による不整合を検知し、適切に対応を行う必要があります。
・DBの分割、KVSの検討
もし、ここまでの対策で追いつかないようであれば、テーブル毎のサーバー分割や、ユーザIDやタイムスタンプによるパーティショニングといった、Shardingを検討する必要があります。また、テーブルの利用傾向を分析し、それぞれに見合った特性を持つKVS等を併用することで、大幅な性能改善が実現できる場合もあります。
具体的な手法については、この連載の目的から離れますので省略します。
・DB Slave
基本的にはスペックアップで対応しますが、DB Masterの構成を変更した場合はそれに追従する必要があります。
・Cache
基本的にはスペックアップで対応します。
アプリがヒットしなかった場合の対策
ソーシャルアプリの場合には、一度公開したアプリの収益が思ったように上がらないからといってすぐに提供を中止することはできず、例えばmixiの場合には提供終了前にmixi事務局に連絡する必要があり、そこから45日間はサービスを続ける必要があります。あるいは、アプリの提供を続けながら企画内容を練り直す場合にも、収益が上がらない期間のコストを削減する必要があります。
上記の計算は全て25%程度の割引効果のある月額プランでの計算となっていますが、料金プランを従量に変更し、インスタンス種別を低スペックのものに落とすことで、その期間のコストを削減することができます。また、アプリのリリース時点では、最低台数分のみを月額プランとし、それを超える台数は従量プランとする使い分けも可能です。
特にソーシャルアプリでは、サーバー過負荷などで離れた利用者が再び戻ってくる割合が少ないため、リリース直後の新着アプリ欄からの新規流入に耐えることができないと、大幅な機会損失となってしまいます。そこで、リリース時点では従量プランで一時的に想定される限界まで台数を増やしておき、実際の負荷を見ながらサーバー台数の最適化を継続して行うことが重要です。
今回のまとめ
ソーシャルアプリの企画・設計段階にサーバーインフラ側で検討するべき事項として、どのようにサーバー費用の試算をするか、また、アプリがヒットしすぎた場合、ヒットしなかった場合にどういうリスク管理をするのか、についてご紹介いたしました。
次回予告: 第2回 アプリの開発と負荷試験 「開発環境の充実はとっても嬉しいなって」
次回は、アプリの開発段階と負荷試験まで進める予定です。
夢の中で思いついたようなアプリを実際に用意しておきます。
------------------------------------
プロフィール
ライターネーム:仲山 昌宏
歌って踊れるインフラエンジニア兼、
PHPもRubyもJavaも書くPerl使い。
物理サーバーの運用に飽きて、フルラックに
格安サーバー詰めて自宅プライベートクラウドを構築中。
今年は個人的には分散処理を攻めていきます。
------------------------------------