AWSクラウドデザインパターンを元にゲーム運営のサーバー構成を見てみる

#はじめに
今回の投稿は gumi の Advent Calendar という事で、会社に関係する 「ゲーム」 と 「AWS」 をテーマに記事を書いてみます。

以前に
[インフラ初心者に勧める「Amazon Web Services 基礎からのネットワーク&サーバー構築」](http://qiita.com/kinpira/items/bc21a0fed8d5a467e6c3)
という記事を書いたのですが、次はAWSクラウドデザインパターンという本を読んでみたので、ゲーム運用で使っているサーバー構成から実際に gumi で使用されているデザインパターンを何個かピックアップしてみます。

[![61mLjsqCPjL._SX386_BO1,204,203,200_.jpg](https://qiita-image-store.s3.amazonaws.com/0/93763/47bea242-fb58-3625-7ea6-cdf51f514b18.jpeg)
](https://www.amazon.co.jp/%EF%BC%A1%EF%BD%8D%EF%BD%81%EF%BD%9A%EF%BD%8F%EF%BD%8E-%EF%BC%B7%EF%BD%85%EF%BD%82-%EF%BC%B3%EF%BD%85%EF%BD%92%EF%BD%96%EF%BD%89%EF%BD%83%EF%BD%85%EF%BD%93-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E8%A8%AD%E8%A8%88%E3%82%AC%E3%82%A4%E3%83%89-%E6%94%B9%E8%A8%82%E7%89%88-%E7%8E%89%E5%B7%9D%E6%86%B2/dp/4822277372)


#AWSクラウドデザインパターンとは
>AWSクラウドデザインパターン (AWS Cloud Design Pattern, 略してCDPと呼ぶ)とは、AWSクラウドを使ったシステムアーキテクチャ設計を行う際に発生する、典型的な問題とそれに対する解決策・設計方法を、分かりやすく分類して、ノウハウとして利用できるように整理したものである。

だそうです。
本にもなっていますが、実はネット上に公開されています。
[AWSクラウドデザインパターン メインページ](http://aws.clouddesignpattern.org/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8)

#登場するサービス
今回は下記のサービスが登場するため、簡単にまとめておきます。

| 名前 | 説明 |
|:-:|:-:|:-:|
| EC2 | 仮想サーバー  |
| ELB  | ロードバランサー  |
| Auto Scaling  | 自動でEC2を立てるサービス  |
| RDS  | リレーショナルデータベース  |
| ElastiCache  | キャッシュサーバー |
| Route53  | DNSサービス  |
| EIP  | 静的 IP アドレス  |
| S3  | クラウドストレージ  |
| CloudFront |  コンテンツ配信ネットワーク (CDN) |
| CloudWatch  | AWS リソースのクラウドモニタリングサービス |
|  VPC |  AWS アカウント専用の仮想ネットワーク |
|  AZ |  地理的に離れた領域のデータセンター |
|  Security Group |  インスタンスの仮想ファイアウォール |


#サーバー構成
今回は下記の「サーバーの構成」図のような構成でゲーム運用をしている事を想定しながら、デザインパターンと照らし合わせてみます。
この図は実際に運用されている構成から一部分を抜き取ってきました。
ちなみに、イメージとしてはスマホアプリから叩かれる APIサーバーを運用している事をイメージしています。

![SQS(1) (4).png](https://qiita-image-store.s3.amazonaws.com/0/93763/431acd85-cb4a-f2ba-0391-63a699b3df37.png)


シンプルな構成図になっていますが、上の図の中でも、可用性や冗長性などを考慮した設計がなされています。
次から、実際にどういったデザインパターンが使われているのかをピックアップしていきます。


# gumi で使われているデザインパターン

##  Multi-Serverパターン（サーバの冗長化）
「サーバーの構成」図で、ELB が複数の EC2 にアクセスしています。
このように複数の EC2 サーバーでアクセスを 捌くのが、Multi-Serverパターンです。

![base 2.png](https://qiita-image-store.s3.amazonaws.com/0/93763/3b1bf4aa-4758-88e4-762d-25e56e2f30cd.png)


利点としては下記が上げられています。
> あるEC2インスタンスに障害が起きたとしても、システム全体としては稼働を続けることができる

APIリクエストを1台のサーバーで受けた場合、単一障害点となってしまいます。
その1台のAPIサーバーに障害が起きた場合にサービスを運用する事が出来なくなります。
ELBを使う事で複数のサーバーで運用する事を可能にしていて、障害時もサービス停止しないように考慮されています。

## Multi-Datacenterパターン（データセンターレベルの冗長化）
「サーバーの構成」図を見てみると AZ が2つ存在していて、EC2 なども両方の AZ に構築されています。
![base 2.png](https://qiita-image-store.s3.amazonaws.com/0/93763/10fe0fbc-82c8-5a47-d91c-1ecbd32a59ea.png)

これが Multi-Datacenterパターン です。

利点としては下記が上げられています。
> データセンターレベルの大きな障害が発生しても、サービス継続可能なシステムを構築できる。

複数のデータセンターにシステムを分散させる事で、災害等が発生して物理的にデータセンターに問題が起きても耐えられるシステムにする事でゲーム運用の可用性を高めます。
複数のデータセンターに分散配置したシステムを、簡単かつ安価にできるからこそ実現可能な手法といえます。

##Deep Health Checkパターン（システムのヘルスチェック）
ELB や Route53 のヘルスチェック機能を使って、紐づけられたシステム全体の健全性をチェックする手法です。

gumi では ELB のヘルスチェック機能でAPIサーバーをチェックしている他に、Route53 のヘルスチェック機能を使って CDN のチェックも行っています。

CDN には AWS の CloudFront の他に Akamai も使用しているため、
普段 Route53 は Akamai を向いているのですが、 Akamai がヘルスチェックに失敗した場合に、接続先が  CloudFront に切り替わる仕組みを取っています。

<img width="319" alt="スクリーンショット_2016-12-12_23_55_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/08540b03-a90a-410a-60f6-c8b97bae5536.png">



##Scheduled Scale Outパターン（サーバ数のスケジュールにあわせた増減）
ゲームの仕様上、アクセスが急増するタイミングが分かっている場合、事前にスケールアウトのスケジューリングをしておきます。
ゲームの場合、仕様によっては決まった時間にアクセスが集中するような場面が多々あるため、そういった場合に自動でスケールアウトさせられるのは管理コストも下がります。
その後、アクセスが落ち着く頃にはスケールインすれば不必要な時にはサーバー台数が押さえられるため、サーバーコストも節約できます。
このデザインパターンの利点は、コストを抑えつつ自動で冗長化を行う事です。

実際のメトリクスで例を上げてみます。
下記の図が2日間のリクエストカウントです。
毎日おなじ時間にな急激な負荷がかかっています。
<img width="636" alt="スクリーンショット_2016-12-11_1_24_36.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/7104b418-e2b3-f15f-9520-3561b6348ade.png">

普段は 1000 リクエストにも満たないのに、毎日決まった時間に 6000 リクエストまではねている場合、常に 6000 リクエストに合わせたサーバー台数を用意しておくと、コストが数倍にかさむ事が予想できます。

そのため、普段は 1000 リクエストに耐えれるだけの低コスト運用にしておいて、決まった時間だけサーバーを増やす事でゲームを維持しつつコストを押さえることに成功しています。

注意点としては、スケールアウト時のサーバーが立ち上がるまでの時間を考慮しておかないといけない点です。
あと、１時間料金の単位で課金が発生するため、その辺りも考慮したスケジューリングを行う事がポイントです。

<img width="657" alt="スクリーンショット_2016-12-12_20_58_49.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/40b17efa-76ef-4482-1f34-cac3e53791a2.png">


## Cache Distributionパターン（ユーザに物理的に近い位置へのデータ配置）
DLC などに使用できる手法です。
ゲームから DLC のデータを S３ に取得しに行く場合に、 CloudFront を利用して、地理的にユーザーに近いロケーションにデータをキャッシュし、より早く安定的にデータをユーザーに届けます。


利点として、この手法を利用する事でユーザーのダウンロード時間が短くなるので、ユーザー体験を極力損なわないようにできます。

<img width="220" alt="スクリーンショット 2016-12-13 16.16.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/6c6fda3e-e86d-b7fe-9659-0c4c7e6f4715.png">


## DB Replicationパターン（オンラインDBの複製）
Multi-Datacenterパターン と似ていますが、こちらは DB のお話で、Replication を他の AZ に持つ事によって、可用性を高める手法です。

利点としては、災害等で障害が起きた場合も DB のフェイルオーバーによる復旧が出来る点です。

ただし、Replication にはデータのラグがある事や、フェイルオーバーで普及するには多少の時間がかかる事は念頭においておかなければいけません。

![base_4.png](https://qiita-image-store.s3.amazonaws.com/0/93763/b3adcdaf-caa2-9a25-4166-8b025359454f.png)



## Inmemory DB Cacheパターン（頻度の高いデータのキャッシュ化）
データベースからの読み込みパフォーマンスを向上する方法として、頻繁に読み込まれるデータをメモリーにキャッシュするという手法です。

利点としては下記になります。
> キャッシュとして高速なメモリーを用いることで、データベースの読み込み負荷を下げ、システム全体のパフォーマンスを向上できる。

この手法は、どのゲームでも頻繁に使っている手法になります。
ちなみに gumi では Memcached ではなく Redis を使用しています。

![SQS_3_.png](https://qiita-image-store.s3.amazonaws.com/0/93763/d16d3a45-e8b0-a073-af3d-b2b9e3d02a95.png)


## Bootstrapパターン（起動設定の自動取得）
サーバーを AMI 等から立ち上げる際に、必要なライブラリやソースコードなどを自動で取得させ、サーバー内部を動的に構築する手法です。

利点としては下記があげられています。
>インストールが必要なパッケージのバージョンがアップデートされたときもAMIを作り直す必要がない

gumi でもこの手法は、オートスケーリングでよく使っています。
特にゲームの本体であるソースコードは頻繁に更新されるため、オートスケーリングが立ち上がる時に、自動で最新のソースコードを取得するようにしています。

![base 4.png](https://qiita-image-store.s3.amazonaws.com/0/93763/33ed2eae-ec09-ffb9-3d90-05eae45fb971.png)

## Cloud DIパターン（変更が多い部分の外出し）
EC2のタグ機能を利用して、タグの内容によって起動時のサーバーの設定や取得情報を変える手法です。
こちらは Bootstrapパターン の応用として使用しています。
APIサーバーやバッチサーバーなど役割が違うサーバーは役割によって、内部の設定や必要なソースコードも変わります。
なので、事前に環境や役割などを表すタグのルールを決めておき、EC2 のタグの内容によって Bootstrap の処理が分岐するようにします。

利点としては下記が上げられます。
> 自動的に設定を行えるため、運用時のミスを低減できる。

ゲーム運用の様に、いろんな環境や役割のサーバーが必要な場合にも、簡単にサーバーの増減ができます。

<img width="533" alt="スクリーンショット_2016-12-12_21_18_22.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/4c2f378c-a79d-fbc2-09a6-e8801bdc31b3.png">


## Monitoring Integrationパターン（モニタリングツールの一元化）
AWSのモニタリングサービスの CloudWatch は仮想サーバー内（OS/ミドルウエア/アプリケーションなど）の監視はできないので、CloudWatch が 提供している API を使用して、自前のモニタリングサービスで一元管理する手法です。

gumi ではこの手法で Zabbix に情報をまとめて一元管理しています。
利点としては、仮想サーバー内の監視も含め一元管理できる他にも、CloudWatch のメトリックの保持期間よりも長期間メトリックじを保持ができるという利点があります。
ただし、現在は CloudWatch の メトリックの保持期間も15ヶ月に増えたので、今では保持期間としての利点はあまりないかもしれません。

![SQS(3) (2).png](https://qiita-image-store.s3.amazonaws.com/0/93763/edd8e70f-8ad3-f8e3-da13-2063a1499086.png)


## Log Aggregation パターン(ログの集約)
ログの集約先として S3 を使うことで、大量のログを安価かつ高い耐久性で保存可能とする手法です。
ゲームでのログは量も多く、重要性も高いため重要なデザインパターンですね。

利点としては下記になります。
> ログ保存用に別途サーバーを立てる必要がなく、収集したログの堅牢性についても意識する必要がなくなる。

弊社でも td-agent を使ってこの手法を実現しています。
このデザインパターンは、ログが欠損しないように S3 等にログを転送するまでの方法が重要となります。

<img width="422" alt="スクリーンショット 2016-12-13 18.08.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/93763/2a187a04-ada4-9dd2-d389-30d021d6e2ab.png">



## Ondemand Activationパターン（メンテナンス時の一時的な設定変更）
セキュリティを担保するため、一時的に起動した踏み台サーバを経由したSSH接続のみを受け付ける手法です。
サーバーをセキュアに運用する為のデザインパターンです。

ちなみに、Ondemand Activation　パターンは、バッションサーバーを立てる方法以外にも「NATサーバの一時的な起動」や、「セキュリティグループの一時的な設定変更」なども紹介されています。

利点としては共通して下記が上げられています。
> サーバーを起動してないときは、システムにログインする経路やインターネットにつながる経路がないので、システムをよりセキュアに保てる。

簡単にサーバーを立てたり削除したりできる、クラウドサービスの恩恵が可能にしている手法だといえます。
それでも接続が必要な度に入り口を立てないといけないので、若干面倒ですが、サービスを運用する為にはこういった手法で堅牢なサーバー構成にする必要があるわけです。

![SQS_4___1_.png](https://qiita-image-store.s3.amazonaws.com/0/93763/0677e7ae-e200-878a-aea7-2ced89b48ae3.png)

## Functional Firewallパターン（階層的アクセス制限）
セキュリティグループと呼ばれる仮想ファイアウォールを使用する事で、機能ごとに簡単にセキュリティグループを作成し、ルールを一元管理するという手法です。

利点として、仮想サーバーへの適用も機能グループ単位で実施できるようになり、アクセス制限のメンテナンスも容易となり、ミスも起きにくくなります。

下の図でもあるように、セキュリティグループどうしでもアクセス権限を設ける事で、アクセス制限をグループ単位で容易に指定出来きます。

![スクリーンショット 2016-12-13 16.20.30.png](https://qiita-image-store.s3.amazonaws.com/0/93763/2da3b586-f5e7-6c10-7241-a197fb77dc7e.png)



#最後に
今回何個かデザインパターンをピックアップしましたが、いつも何気なく見ていたサーバー構成もやはりちゃんとこういった知識を元に構成されている事を実感しました。
今回は gumi の構成の一部を元にピックアップしましたが、他にもたくさんのデザインパターンが存在していています。
自分で構成を考える際は、必ず念頭に置いておきたい知識のため、AWSでこれからインフラを学ぶ人は是非一読しておく事をお勧めします。