アプリがTVCMを実施した際の負荷対策

この記事は GRIPHONE Advent Calendar 2020 2日目の記事です。

こんにちは。サーバーサイドエンジニアの西村です。
今回はアプリがTVCMを実施した際の負荷対策についてお話したいと思います。

総括

最初に総括をお伝えすると

  • CM後に負荷はスパイクしない
  • 負荷は徐々に増えていく
  • 見積もりから数値がずれたら原因を調べる

になります。

グループ会社にヒヤリング

自分が携わっているアプリで様々な方が協力した結果TVCMを実施する!と決まりましたが、サーバー的には負荷がどのように推移するのか全く分かりませんでした。
そこでTVCMを実施した事のあるアプリに携わっている関連する会社の方々にCM時の負荷についてヒヤリングを行いました。
グループ会社の内容をざっくり取りまとめると

  • CM後にスパイクしない
  • 負荷は徐々に増えていく
  • 流入数はGRPなどの数値通り

ということでした。
ここをひとつひとつ見ていきましょう。

CM後にスパイクしない

TVCMを実施すると、その開始時間から異常な流入が来る、と思っていた自分からすると目からうろこでした。
なので、CM開始時に大きくAPIサーバーの台数を増やす必要はなさそうです。
(もちろんアプリの形態で変わるので一概に上の通りではないと思います)

負荷は徐々に増えていく

ユーザーが期間に応じて積みあがっていく傾向があるので、DBなどのデータが積まれていくようになります。
TCVM期間にボトルネックが無いように準備をしましょう。
サーバーのプログラムの問題やDBのスロークエリなどの問題を極力事前に解消しておいたり、施策の前後に大きな施策を極力入れないように調整する、などになると思います。

流入はGRPなどの数値通り

GRPという言葉を聞いても (。´・ω・)? 状態でした。
関連する会社の方から聞いたのはこのようなマーケティングチーム側が持っている流入目標の数値に近い数が来る傾向があるので、マーケティングチームと連携してこの数値を共有してもらい、その数値に対応できるように準備をしましょう。
参考リンク:https://www.television-ad.com/ad-basic/grp.html

負荷見積もり

上のように負荷と流入について概ね分かったので、あとは自分たちで負荷を試算しました。
ここでは過去最大負荷と比較してTVCMの想定負荷を見積もりました。
負荷試験とその記録を必要に応じて行っており、アプリの過去最大負荷も記録に残しており、増強するサーバーの算段が立てやすかったです。
アプリで記録した過去最大負荷を下記のように想定します。
(単位は仮の数値になります)

ユーザー数10リンゴ人
APIサーバー70バナナ負荷
DBサーバー80みかん負荷
キャッシュサーバー20いちご負荷

ここで現状のユーザー数(仮に8リンゴ人)とTVCMの流入見積もり数(仮に8リンゴ人)を元に負荷を試算します。

ユーザー数8 + 8 = 16リンゴ人
APIサーバー70 * 1.6 = 112バナナ負荷
DBサーバー80 * 1.6 =128みかん負荷
キャッシュサーバー20 * 1.6 = 32いちご負荷

上の様に計算をしてその負荷に応じて各サーバーを増強するかどうか検討しました。
今回のボトルネックになりそうだったのが、APIサーバーとDBサーバーの負荷でしたので、ここについて対策を考えました。

APIサーバー

今回は基本的にPublicCloud側にあるAutoScalingの機能でどこまで増やすか、に頼りました。
ただCM前にサーバーを増やすなどは検討した方がいいと思います。
必要であればDBサーバー・キャッシュサーバーの接続の処理なども見直す必要があると思いますが、自分たちは必要がありませんでした。

DBサーバー

DBが負荷に耐えれないのでメンテします!が基本許されないので負荷が捌けるように増強しました。
スロークエリなどの見直しをしておくべきです。

キャッシュサーバー

想定以上にユーザー数が増えた場合、キャッシュサーバーが詰まる可能性があったのでキャッシュサーバーを増強する準備をしておきました。
ただしこの対応はリリースしませんでした。

その他

また今回は考えませんでしたが、アプリの状況(TVCMとリリースが同時の場合など)によってはサーバーの暖気も検討した方が良いかもしれません。
上には挙げていないアセットバンドルサーバーも暖気の対象になると思います。

TCVM中

TVCMが始まりユーザー数が増えていき負荷が伸びてきましたが、グループ会社から聞いた通り

  • CM後負荷はスパイクしない
  • 負荷は徐々に増えていく
  • 流入はGRPなどの数値通り

でした。
ただ一部の負荷で見積もりと違う状態になりました。
ここではユーザー数が4リンゴ人流入して、12リンゴ人だと仮定します。

ユーザー数8 + 4 = 12リンゴ人
APIサーバー70 * 1.2 = 84バナナ負荷
DBサーバー80 * 1.2 = 116みかん負荷(96にならず)
キャッシュサーバー20 * 1.2 = 24いちご負荷

DBサーバーの負荷が見積と違うなー・・・となりましたが、当時の自分は
「過去最大負荷時と今(TVCM期間時)でアプリに大きく機能差分があるからかな」
と思っていて、この差分の原因調査を行いませんでした。
その後、TVCM中の最大負荷を迎えました。
ここではユーザー数が8リンゴ人流入して、16リンゴ人だと仮定します。

ユーザー数8 + 8 = 16リンゴ人
APIサーバー70 * 1.6 = 112バナナ負荷
DBサーバー80 * 1.6 =168みかん負荷(128にならず)
キャッシュサーバー20 * 1.6 = 32いちご負荷

概ね想定通りの負荷だったのですが、DBサーバーのみ負荷の伸びが見積もりとずれ、大きく伸びました。
実際の負荷はこのようになっておりました。

高負荷の状態では一部機能でレスポンスが遅くなっておりましたが、幸い時間と共に負荷は下がりレスポンスの速度が戻り、事なきを得ました。

上の原因はDBで使用頻度が高いテーブルに適切にindexが張られておらず、スロークエリが大量に出ていました。
そのテーブルは負荷試験対象外だった事が判明しました。
負荷試験対象外だった理由はプラットフォームに大きく依存する所だったためです。
今ではこちらの問題の解消はされております。
事前準備でスロウクエリの確認が出来ていなかった事も問題でした。
こちらは高負荷にならないと出ないスロウクエリだったので実行されているSQL文を全てEXPLAINするなど行うべきでした。

様々な点で準備不足、かつ適切な対応を行わなかった事を反省しました。

最後に

改めて最初の総括に戻ります。
私たちのアプリでTVCMを実施して学んだ事は

  • CM後に負荷はスパイクしない
  • 負荷は徐々に増えていく
  • 見積もりから数値がずれたら、原因を調べる

になりました。

事前準備はとても大事ですが、実施中に値が見積もりから大きく外れた場合はきちんと見直さないと大変な事になる、ということを改めて感じました。
TVCM自体あまり実施する内容ではないと思いますが、改めて貴重な経験をさせていただいたと同時に、適切に負荷を捌けずユーザー様にご迷惑をおかけした事が申し訳ない気持ちでいっぱいです。

最後になりますが協力して頂いたサーバーチーム、SREチーム、マーケティングチームの皆様ありがとうございました _(._.)_