エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

絶対に落とせない!友人の結婚式の余興用アプリケーションをエラーゼロで突破した

エムスリーエンジニアリンググループ AI・機械学習チームでソフトウェアエンジニアをしている中村(po3rin) です。検索とGoが好きです。

今回は友人の結婚式の余興用に作ったアプリケーションの実装とエラーゼロで突破するための工夫などを紹介します。

どんな余興をしたの?

友人とは毎年夏の旅行で「格付けチェック」をやっていて、高い肉や酒を当てられるかなどのゲームをしているので、今回の友人の結婚式の余興では「格付けチェック」と題して、新婦はプロに混じった新郎の作品を見分けられるか?という企画を行いました。

  • 新郎が書いた現代アートはどれ?
  • 新郎が書いた曲はどれ?
  • 新郎が書いた本物のラブレターはどれ?
  • etc…

例えば下記の中で1つは新郎が書いたもので、それ以外はプロの現代アートです。

どれが素人の絵?

(正解はこの記事の最後に)

プロと新郎の作品を見分けるだけなのでゲストももちろん参加可能です。よって回答システムを作って優勝者に賞品を出しました。

アーキテクチャ

Cloud RunでGoで作ったAPIをデプロイしてLINE BOTを作成しました。LINEで回答選択用ボタンをpushし、ゲストに回答してもらう形にしました。回答はCloud SQLに保存しています。

この構成を作った所感としてはリリースがかなり楽で、さくっと何か作るならCloud Run × SQL構成はおすすめです。

各種ドキュメントはこちら

Cloud Run cloud.google.com

Cloud SQL cloud.google.com

LINE Messaging API developers.line.biz

結婚式で使う回答システム実装のポイント

  • 本番直前1ヶ月は動作確認ができないことを考慮したスケジューリング
  • 本番は15分だけなので、それ以外の時間はなるべく料金は安く済ます。
  • 絶対に落とせないアプリケーションのための負荷試験、Fuzz testing

本番直前1ヶ月は動作確認ができないことを考慮したスケジューリング

LINEで回答選択用のコンポーネントをこちらからpushして、ゲストはそのコンポーネントで回答を選択できるようにしていたのですが、messageing APIのpush数には制限があり、1ヶ月で1000件しか送れません。

上記は下記のサイトから引用した図です。 www.linebiz.com

参加者150人いる場合、形6問で合計900通を本番で送ることになるので、本番アカウントで動作確認できるのは100通くらいになります。よって、本番アカウントでの動作確認は念のため1ヶ月前に終わらせる必要があるので、開発スケジュールは1ヶ月前にほぼ完成するように設定しました。

本番以外の時間はなるべく料金を安く済ます。

当然ながらCloud Run × SQLはある程度の料金がかかります。QA環境の最小構成でも約1ヶ月で約3000円かかりました。

本番は絶対に落とせないので、本番の日だけリソースをあげて、cold start対策のインスタンス最小数を上げるなどを行ないました。

特にcold start問題は Cloud Runを初めて使う時にはハマるポイントです。結婚式当日にcold startでLINEからのアクセスがタイムアウトしないようにインスタンス最小数を1以上に設定しておく必要があります。一方でdev環境やQA環境のアイドルインスタンスは常時立っていてもコストが発生するだけなので最小インスタンスは0にしておきます。

Cloud Runのcold startに関しては下記の記事が参考になります。

https://cloud.google.com/blog/ja/products/gcp/3-ways-optimize-cloud-run-response-times

また、料金を下げる工夫として、余興が終わったらインフラを全て削除するために、 Terraformで全てのインフラを準備して、結婚式が終わったらボタン一個で削除できるようにしておきました。

これだけやってもトータルで10000円くらいかかってしまいました。

クラウドでかかったコスト

絶対に落とせないアプリケーションのための負荷試験、Fuzz testing

負荷試験

本番には絶対に落とせないので、念のための負荷試験をlocustで行ないました。ふざけて回答ボタンが連打されることも考えて1000req/sを耐えられるか確認しました。

注意点としてはLINE messaging APIを経由した負荷試験は禁止されています。

LINEプラットフォームから、ボットサーバーに負荷テストを行うサービスはありません。負荷テストを目的に、大量のメッセージをLINEプラットフォームを経由して送信しないでください。ボットサーバーの負荷テストを行うための環境は、別途用意してください。

そのため、完璧な負荷試験はできませんでした。そこでLINE message API無しでも回答ができるようにAPIの口を作り、それを利用して負荷試験を行いました。

Fuzz testing

気づかない境界値などがあってエラーが出るかもしれないので、GoによるFuzz testingを行ないました。

Fuzz testingで自動で大量の入力を生成してエラーにならないか確認するテストをすることで、結婚式当日を迎える際の不安が少し払拭できました。

GoにおけるFuzz testingではGo1.18からFuzz testingの機能がサポートされているので、それをそのまま利用できました。

コードとしてはtesting.Fを利用することでFuzz testingを記述できます。

package foo_test

import "testing"

func FuzzFoo(f *testing.F) {
    f.Log("all good here")
    f.Fuzz(func(*testing.T, []byte) {})
}

詳しくは公式のブログをご覧ください。

go.dev

結果

エラーゼロで結婚式を突破できました(Sentry調べ)!!!!!!

Sentryのスクリーンショット

まとめ

  • 数分間だけ耐え忍ぶだけのAPIを作る際には少し工夫すればコストを抑えられる
  • 絶対にエラーを出さないという気持ちで、1ヶ月前倒しスケジュール、負荷試験、fuzz testingなどやれることは全部やればエラーゼロでいける!

皆さんも自分や友人の結婚式の余興などでアプリケーションを開発するときの参考になれば幸いです。

(ちなみに最初に提示した問題の答えはBでした!)

ちなみにYoutubeでも公開しているので、こちらもぜひ!

www.youtube.com

We are Hiring!

エムスリーでは結婚式でアプリケーションを作っちゃうようなギークなソフトウェアエンジニアを募集しています。「ちょっと話を聞いてみたいかも」という人はこちらから!

jobs.m3.com