自己紹介と会社紹介

辻天斗氏(以下、辻):「通知機能をマイクロサービス化していたらユーザー一斉通知でしくじった話」をしていきます。内容としては、こんな感じです。

話す人は、辻と言います。Seibiiでエンジニアをしています。今、組織の規模としては小さいので、インフラ、バックエンド、フロントエンド、アプリを全般的にやっている感じです。

まずSeibiiの話をします。Seibiiは出張でクルマの整備と修理をするWebサービスです。お客さまの自宅に出張で伺うのが、従来型の店舗にお客さまが行ってクルマの整備をするところと大きく違うところです。

2019年1月に設立し、累計で10億円くらい調達している企業です。

Seibiiのバックエンド

まず通知の話をする前に、Seibiiのバックエンドってどうなっているのという前提の話をします。メインのものはモノリシックになっていて、今はseibii-apiに集約されている構成になっています。通知を配信するところだけ、RubyのHanamiというフレームワークを使って切り出しているかたちです。ここからお客さまや整備士に対してそれぞれ通知を配信しています。

なぜ基本モノリシックにしているかというと、やはり開発の体制というか、組織が小さいので、開発スピードを極力上げていくためには、やはりモノリシックにするほうがいいということです。では、なぜ通知だけマイクロサービスにしたのかというと、やはりサービスが増えたときには通知を共通化したいという話です。あと、そもそも配信だけなので変更可能性が少ないだろうから、あまりメンテコストがかからないのではないかと踏んで、やっています。

朝から届く、利用規約改定のお知らせ

ここから本題に入ります。ある日、「そろそろ稼働を始めようかな」と朝起きて準備してメールを見てみると、利用規約改定のお知らせが朝っぱらから5件来ている状態でした。実際のスクショは3件だけなんですけれども、朝から障害だな、もう「ぴえん」という感じです。

でも、そんなに「ぴえんぴえん」言っていてもなにも始まらないので、とりあえず血を止めなければということで、まずメールの送信ジョブを確認しました。そしたら、「あれ、期待の件数の10倍以上に膨れ上がっていて、このままだとさらに倍以上送られてしまうな」と思ったので、仕方なく本番通知DBを直で操作して、該当ジョブを消しました。

すぐできる対応としては、これでいったん収まったかと思いました。とはいえ、メールの配信にSendGridを使っているんですけれど、「SendGrid上で止まっているところがあるんじゃないのかなぁ」と思って、並行してまた別の調査をしようとしました。

ただ、ちょっと時期が悪くて、デプロイできない問題が別件で発生していました。とりあえずこれも早く回復しないと修正できないので、これも対応しましょうということで、チーム全員で、並行して進めるかたちにしました。

そもそもなぜデプロイができなくなっていたのかというと、これはタイミングの問題です。Railsを使っているみなさんならもしかしたら見当がつくかもしれませんが、一時期GPLになっているファイルが混入している問題がありました。

mimemagicというgemがありますが、過去のものがすべて消されて取得できなくなった結果、ECSの本番コンテナやステージングのコンテナをビルドできなくなってデプロイができないことがあったので、これの対応をしなければ、という話になりました。

失敗したジョブは時間差で生き返る

すると、また「あれ、通知が飛んできたぞ、終わってないのかな?」ということで、ちょっともう「ぴえん」じゃなくてその上の「ぱおん」という感じになりました。

これもほかのエンジニアが同時に見ていたので、そもそもAPI側のジョブは生きている、生きているというか蘇生していたということでkillしました。チームで対応したので、すばやくできた面もあります。

Sidekiqって、失敗したジョブは時間差で生き返るので、1回殺したから落ち着くのは幻想だと、今後気をつけなければいけないと思いました。

不整合発生については、あとの質疑応答で質問してください。

しくじりからの反省点とよかった点

反省点として、焦っているときこそ根拠を大切にしましょう。思いつきでプログラムの動きを推測して収束と思い込まないようにしたほうがいいというのがあります。やはり収束の宣言というか判断をするときには、しっかり設定値やソースコードやデータをそれぞれ指し示して、言語化してて、「ここまで来ていればさすがに収束だよね」というところまで、ていねいにやるべきです。

逆に良かったところとしては、やはり障害のときは1人じゃなくて、今回チームメンバー全員でやっていたことによって、見過ごしがあっても早く気づけたので、本当の本当の最悪ケースにならずに済んだのかなと思っています。

今、Seibiiではエンジニアを募集しています。右上にWantedlyのQRコードがあるので、読み取ってもらえれば。ぜひカジュアル面談をしたいですという宣伝です。ひととおり、本編としては以上です。

質疑応答

田仲紘典氏(以下、田仲):辻さん、ありがとうございます。では、僕から質問をいくつかしていこうと思います。ELBのタイムアウト問題のことも聞きたいんですけど、ちょっとその前に。平たく言えば、もしかしたら品質保証のラインとかで解決する部分もあるんじゃないかと思って聞いていました。

用意していた環境ってどういったものがあったんですか? たぶん手元でローカルで開発する環境と本番環境があって、その間はどうなっていたのか聞きたい。

:それで言うと、手元のローカル環境があって、あとはステージングと、今は本番のみです。Dev環境は特に用意していなくて、そのステージング・本番・ローカルの3つだけでやっていました。

品質保証で言うと、そこもしくじりポイントなんですが、この一斉通知の機能を、リリースした直後に使わなかったというのがあります。半年くらい経って使ったら、案の定爆発したみたいな。案の定というか、「あっ、今使われたかぁ」という感じでした。

だから、そもそもリリースしたものがちゃんと動くことを保証できていない状態だったというところも、反省点としてあります。なので、リリース直後に負荷テストをやるべきだったとは思います。

田仲:なるほど。たぶんリリースされちゃっていたという感じなんですよね。ステージング環境なんて絶対いっぱいテストをしているはずじゃないですか。動くかどうかみたいな。

:そうですね。

田仲:「問題ないよね」というところはちゃんとあって、ちゃんと本番にリリースされると思うんですけど、そこはどういったリリースフローで、どうやってみんなで承認されていたのかをちょっと聞たいです。

:ステージングではテストをしていたんですけれど、ステージングのデータ量と、本番のデータ量というかユーザーのレコードの数を合わせてテストをしなかった。なので、本番並みの負荷がかかっても正常に動くかというテストが漏れていたから、というのが一番大きいと思っています。

そこを担保する仕組みを考えないといけないというよりは、これからは、ある程度コストを割く判断をしていかなければいけないということです。今までは、機能をリリースした当初はそんなにユーザー数がいなかったので、そこでちょっと齟齬が起きてしまったのかなという反省点はあります。

しくじりの真因

田仲:では、ELBのタイムアウト問題について聞きたいです。

:ありがとうございます。結論としてはやはり、seibii-apiとnotificationのHTTPベースでやりとりをしている間にELBがいて、ELBが実はデフォルト値よりずいぶん短い値に設定されていたことに、レビューのときも気づいていなかった。

そもそもなぜ違う値になっていたかというと、公開用のものをそのままコピペして内部用のELBに貼り付けてしまっていた。案の定、想定と違う挙動になっていたのが反省点としてあるので、マイクロサービス化するときは、タイムアウトは長く取りましょうということです。こういう一斉通知みたいに急に積むような処理がある場合は、長めに積みましょうというのが別枠の反省点としてあります。

スライド27

田仲:これはありがちな感じですね。

:そうですね。いや、忙しいからといってコピペをして、そこでちゃんと精査しなかったのは反省点です。

田仲:なるほど、ありがとうございます。SQSを使って非同期にするのもよさそうですね。

:そうですね。

田仲:そうですよね。辻さん、ありがとうございました。