DMM.comの、一番深くておもしろいトコロ。

オンプレミス環境からAWSのサーバーレスにリプレイスした話

オンプレミス環境からAWSのサーバーレスにリプレイスした話

はじめに

DMM GAMES プラットフォーム開発本部PFシステム部の李です。
私が所属しているグロースハックチームでは、新規ユーザーの獲得や既存ユーザーの継続利用を促進するための施策を企画・開発しています。

しかし、短期間で機能追加や仕様変更を繰り返した結果、一部コンテンツにパフォーマンスが良くないコードが繁殖してしまいました。
また、そのコンテンツが原因で高負荷時にGAMESプラットフォーム全体が重たくなってしまうこともあり、そのたびに原因調査やコンテンツの復旧作業を行うため、アプリケーション開発に集中できない状態が続いていました。

そのような状況の解決を目標とし、機能単位でのマイクロサービス化・疎結合化を進めるにあたり、DMM GAMESの一部コンテンツをオンプレミス環境からAmazon Web Service(※以下、AWS)へリプレイスしました。

今回は、AWS移行時にポイントとなった4点についてお話したいと思います。

① マネージドコンポーネントを使ったAPIの構成
② 負荷試験
③ DynamoDBへのデータ移行
④ スパイクアクセスへの対応

① マネージドコンポーネントを使ったAPIの構成

今回のリプレイスでは機能単位にマイクロサービス化を図り、疎結合にするため、各々をAPI化することに決めました。

また、インフラ面での運用負荷を下げてアプリケーション開発により集中できるようにするため、EC2は利用せずにマネージドサービスを最大限活用しました。
主に利用したAWSサービスは以下となります。

  • Amazon API Gateway(※以下、API Gateway)
  • AWS Lambda(※以下、Lambda)
  • Amazon DynamoDB(※以下、DynamoDB)
  • Amazon Kinesis Data Streams(※以下、Kinesis Data Streams)

負荷に応じて、2パターンの構成を使い分けました。
具体的には、高負荷が予想されるAPIではKinesis Data Streamsを挟み、処理結果を待たずレスポンスを返すようにしました。

▶︎ パターンA

高負荷にならないと予測されるAPI、クライアントに処理結果をレスポンスする必要のあるAPIは、この構成を採用しています。
クライアントからのリクエストをAPI Gatewayで受け付けます。API GatewayではSwagger仕様準拠のJSONを利用して、リクエストパラメータのバリデーションチェックを自動で行っています。
バリデーションチェックが問題なければ、Lambdaファンクションを起動します。
Lambdaファンクションは受け取ったリクエストパラメータをもとに処理を行い、DynamoDBのテーブルにデータの追加・更新をしています。

f:id:dmmlabotech:20180802125934p:plain

▶︎ パターンB

高負荷が予測されるAPI、かつクライアントにレスポンスが不要なAPIは、この構成となっています。
API GatewayからKinesis Data Streamsにデータが入った時点でユーザーにレスポンスが返ります。
Lambdaが非同期でKinesis Data Streamsからデータを取得し、DynamoDBのテーブルにデータを追加・更新しています。

f:id:dmmlabotech:20180802125951p:plain

上記2パターンともサーバレスなつくりのため、リプレイス前と比べてインフラの管理・監視が楽になりました。

② 負荷試験

今回のリプレイスでは高負荷時でも正常にリクエストを処理できるようにするという目的があったため、5,000リクエスト/秒 あった場合でも非機能要件で決められたレスポンスタイムより早くすることをゴールとして負荷試験を行いました。

JMeterをインストールしたEC2 15台から同時に負荷をかけて、メトリクスを確認しながら各サービスの設定値を調整しました。
Kinesis Data Streamsにデータが溜まって処理遅延が起きそうな場合はシャード数を増やし、Lambdaで遅延が起きた場合はメモリ数を上げました。
今回の構成ではマネージドサービスを利用しているため、パフォーマンスに関わる設定はとてもシンプルです。

サービス名 設定内容
API Gateway キャッシュの有無
Lambda メモリ量、バッチサイズ
DynamoDB Read Capacity Units
Write Capacity Units
Kinesis Data Streams シャード数

リリース後、イベント開催で高負荷になることがありましたが、リクエストを正常に処理できるようになりました。

③ DynamoDBへのデータ移行

リプレイスにあたりテーブル構成等を再検討していくなかで、DynamoDBへの移行を行うことになりました。

今回は、AWS Direct Connectを利用して、データ移行を行いました。
まずAWS Direct Connectを使ってオンプレミス環境から移行データを取得し、マッピングデータをDynamoDBに登録するスクリプトをEC2から実行することで、オンプレミス環境のデータベース(MySQL)で管理していたデータをDynamoDBに移行しました。

また、移行データの整合性チェックもAWSサービスを使って行いました。
DynamoDB Streams(トリガー設定が必要)を使って、移行先のDynamoDBのテーブルにデータが登録されたタイミングで、チェック用Lambdaファンクションで移行データを読み込みます。
その移行データを、再度Direct Connect経由で取得したオンプレミス環境のデータと比較して、チェックを実施しました。

f:id:dmmlabotech:20180802130027p:plain

④ スパイクアクセスへの対応

DynamoDBでAutoScale設定をするとキャパシティーが自動で拡大・縮小されるためとても便利ですが、スパイクアクセスには対応しきれないというデメリットがあります。
DMM GAMESではアクセス数の多い時間帯がある程度決まっているため、Lambdaファンクションでキャパシティーの調整をしています(CloudWatch Eventsでルール設定)。
図の青線が実際に消費しているキャパシティーで、赤線がプロビジョニング済みのキャパシティーの値です。

現時点では1日1回上げ下げを行っているため、余分なキャパシティーを確保している時間帯もあります。
将来的にはAmazon SageMakerを利用して消費するキャパシティーを学習させることでアクセス予測を行い、プロビジョニングするキャパシティーも自動で調整できればと考えています。

f:id:dmmlabotech:20180713175810p:plain

最後に

いかがだったでしょうか? 今回はAWS移行時にポイントとなった4点についてお話させていただきました。

リプレイスで機能単位でマイクロサービス化した結果、疎結合で拡張性が高いシステムに生まれ変わることができました。
そのおかげで、仕様変更にも柔軟に対応することができるようになりました。
また、高負荷時にプラットフォーム全体を重たくしてしまうような巻き込み障害もなくなったため、インフラ面での運用負荷も軽減され現在はアプリケーション開発に集中することができています。

プロジェクト内で使用するAWSサービスも徐々に増えており、最近だとCloudFormationでリソースをテンプレート管理したり、Athenaを使ってS3に出力したログ分析を行ったりしています。

今後もさまざまなサービスを活用して、よりコンテンツを充実させていきたいと考えています!

採用情報

現在、DMM GAMES PFシステム部では、エンジニアを募集しております! 興味のある方はぜひ下記募集ページをご確認下さい! dmm-corp.com