$30 off During Our Annual Pro Sale. View Details »

小さなバグが生んだ悲劇、そこから学ぶ耐障害性の高いアプリ設計

Yosuke Imairi
September 02, 2023

 小さなバグが生んだ悲劇、そこから学ぶ耐障害性の高いアプリ設計

iOSDC Japan 2023 にて登壇した内容となります。
https://fortee.jp/iosdc-japan-2023/proposal/eb9d4449-4ff8-421d-9ffb-691179245d14

登壇のアーカイブ
https://www.youtube.com/watch?v=9GbG13-jMVM

Yosuke Imairi

September 02, 2023
Tweet

More Decks by Yosuke Imairi

Other Decks in Technology

Transcript

  1. © GO Inc.
    2023.09.02
    タクシーアプリ『GO』iOSアプリ開発 マネージャー / 今入庸介
    GO株式会社
    小さなバグが生んだ悲劇、
    そこから学ぶ耐障害性の高いアプリ設計

    View Slide

  2. © GO Inc.
    自己紹介
    2
    プロフィール写真
    GO株式会社
    ユーザーシステム1グループ / 今入庸介
    タクシーアプリ『GO』のiOSアプリ開発
    ● 新機能開発
    ● アーキテクチャの選定・導入
    ● アプリ全体の設計、新機能開発
    ● CI 環境の構築・整備、自動化の促進
    ● チーミング、エンジニアの育成
    @kamekiti

    View Slide

  3. © GO Inc. 3
    はじめに
    タクシーアプリ『GO』で起きた実際の障害事例をもとに
    ● 障害が起きたときに適切に対処するにはどうすればよいのか
    ● 同じ障害を起こさないためにどのように対策をとればよいのか
    について考える

    View Slide

  4. © GO Inc.
    タクシーアプリ『GO』で発生した
    実際の障害事例
    4

    View Slide

  5. © GO Inc.
    〜 iOS アプリのリリースの翌日 〜
    5
    小さなバグが生んだ悲劇(タクシーアプリ『GO』での障害事例)
    iOS アプリ起動後に異常な数のリクエストが送られていることが判明 💥
    (通常の数百倍のリクエスト…!ローディング状態が続き次に進めない)
    社内で「一部のサービスへのリクエストが異常に減っている」との連絡
    (どうやらタクシー配車依頼までユーザが辿り着けていない 🤔)

    View Slide

  6. © GO Inc. 6
    小さなバグが生んだ悲劇(タクシーアプリ『GO』での障害事例)
    しかし、アプリ側でメンテナンスモードに切り替わらない 😰
    正確には、切り替わったり切り替わらなかったりする
    サービスが提供できなくなりメンテナンス状態に変更(サーバサイド)
    アプリ内部のバグを修正して App Store Connect の特急審査に提出 🚀

    View Slide

  7. © GO Inc.
    それから数日が経ち、修正版のアプリが全体の 80% に浸透して平和に 😌
    7
    小さなバグが生んだ悲劇(タクシーアプリ『GO』での障害事例)
    リリース後、修正版のアプリがユーザに浸透することを祈る 🙏
    バグを含んだバージョンの利用を抑えたい!
    2時間45分で審査に通過し、即リリース

    View Slide

  8. © GO Inc. 8
    障害時の対応がよくなかった
    1. メンテナンス状態なのにアプリ側で適切な対応ができなかった
    ○ メンテナンスモードに切り替わらなかった
    ■ アプリの初期段階からメンテナンスモード自体は実装されていた
    ○ ユーザを混乱させてしまった
    ■ これは障害?一時的に負荷が高い状態?
    ■ ユーザ側の環境の問題?(電波が悪い etc..)
    2. バグを含んだバージョンの利用を抑えることに時間を要した
    ○ 修正版のアプリに更新してもらうことをただ祈るのみ…

    View Slide

  9. © GO Inc.
    メンテナンスモードで
    被害の拡大を抑制、状況説明をする
    9
    耐障害性の高いアプリ設計 その1

    View Slide

  10. © GO Inc. 10
    メンテナンスモードとは?
    ● アプリ内の特定またはすべての機能の利用を遮断させる
    ○ 通常どおりのサービス提供ができないため
    ● 想定される利用シーン
    ○ 予期せぬ障害
    ○ 定期メンテナンス

    View Slide

  11. © GO Inc.
    ● メンテナンス状態のときにユーザに現状の報告ができる場
    ○ アプリ内でユーザに現状を明確に伝える
    ■ 障害なのか定期メンテナンスなのか
    ■ いつ復旧するのか
    ● 復旧の目処が立たないという情報だけでも有益
    ○ WebサイトやSNSなどで障害情報を発信できるがあくまで補助的
    ● ユーザはアプリを使いたいのに使えない状態であることを肝に銘じる
    ○ これはユーザにとって最悪の体験の1つとなる
    11
    メンテナンスモードで何を伝えられるとよいか

    View Slide

  12. © GO Inc.
    ● 根本的な原因は、API に依存した設計になっていたこと
    ○ メンテナンス状態かどうかを API 経由で取得していた
    12
    なぜ『GO』はメンテナンスモードに切り替わらなかったのか
    iOSアプリから通常の数百倍のリクエストが送られる(バグ)
    GO のサーバや DB に負荷がかかり捌けなくなる
    アプリは API からメンテナンス状態を受け取りたいが、API のレスポンスが返ってこない
    アプリ上は通信中状態のまま(ユーザには何が起こっているか分からない)

    View Slide

  13. © GO Inc.
    ● JSONファイルの取得に成功した場合のみ、その状態を適用させる
    ● iOS / Android で別々のファイルで管理
    ○ どちらか一方だけで障害が起きる可能性がある
    ● サーバ・DB に依存しない場所でメンテナンス状態を管理する
    ○ 『GO』の場合は GCS に JSONファイルを配置
    ○ メンテナンス状態かどうかを Bool 値で管理
    13
    メンテナンス状態かどうかの判断をどうやるか【障害時】
    {"is_maintenance":false}

    View Slide

  14. © GO Inc.
    ● 障害時と同様でもよいが、APIが相応の状態を返してもよい
    ○ 定期メンテナンスを判断する API を用意
    ○ 機能の一部として利用している API の状態を利用
    ■ API ごとにハンドリングできるので、細かな制御がしやすい
    14
    メンテナンス状態かどうかの判断をどうやるか【定期メンテナンス】

    View Slide

  15. © GO Inc.
    強制アップデート機能で
    迅速に修正版のアプリを届ける
    15
    耐障害性の高いアプリ設計 その2

    View Slide

  16. © GO Inc.
    ● ユーザに対してアプリのバージョンアップを促す機能
    ○ ユーザはアプリを更新するまでアプリ内の機能が利用できない
    ● 想定される利用シーン
    ○ アプリ内部にバグがあるバージョンの利用を抑制したい
    ○ 古い機能のサポートを終了したい
    ○ ユーザに届ける体験を統一したい
    ■ ユーザによって利用できる機能に差がないようにする
    16
    強制アップデート機能とは?

    View Slide

  17. © GO Inc.
    ● バージョンアップしないとアプリの機能が使えない旨を伝える
    ○ なぜバージョンアップしないといけないのかの説明もあるとよい
    ● ユーザに対してバージョンアップを誘導する
    ○ App Store や Google Play への導線を配置する
    17
    強制アップデート機能で何を伝えられるとよいか

    View Slide

  18. © GO Inc.
    ○ needs_update_versions: 指定されたバージョンが対象
    ○ required_app_version: 指定されたバージョン未満すべてが対象
    ● 『GO』の場合は、GCS に iOS / Android で個別の JSON ファイルを配置
    ○ メンテナンス状態の管理と同じ思想
    ● 強制アップデートを要求するアプリバージョンを記載する
    18
    強制アップデートが必要かどうかの判断をどうやるか
    {
    "needs_update_versions": ["6.7.0”, “6.7.1"]
    "required_app_version": "6.5.0"
    }

    View Slide

  19. © GO Inc.
    ● アプリを起動した直後が理想
    ○ 可能な限り早い段階で判断したい
    ■ アプリ内の機能が利用される前
    ○ アプリ内部のバグはどこに潜んでいるか分からない
    19
    強制アップデートを要求するタイミング

    View Slide

  20. © GO Inc.
    ● 今回の障害時のタイミングでは『GO』には強制アップデート機能がなかった
    ○ 修正版をリリース後、アプリが更新されることを祈るしかなかった
    ● Karte の接客テンプレートを使い、バグがあるバージョンに対して
    起動後にアプリのバージョンアップを促すようにした
    ○ 告知は閉じられたので、やや強制力は弱め
    20
    余談:今回の事例で『GO』はどのようにアップデートを促進したのか?

    View Slide

  21. © GO Inc.
    根本的な原因の追究と対策
    21
    耐障害性の高いアプリ設計 その3

    View Slide

  22. © GO Inc.
    ● 同じ過ちを繰り返さないようにしたい
    ○ なぜ今回の事象が発生したのかをチームメンバーと振り返る
    ○ 根本的な原因は何だったのか?
    ○ どうすれば防ぐことができたのか?
    ● 『GO』では今回の事例を受けて以下の対応をした
    ○ メンテナンスモードの改善( サーバ / DB に依存しない設計)
    ○ 強制アップデート機能の追加
    ○ ”目に見えないバグ” への対処(後述)
    22
    障害が落ち着いたら終わりではない

    View Slide

  23. © GO Inc.
    ● 今回の障害の原因
    ○ コード誤り(ケアレスミス)
    ● 今回の障害の詳細
    ○ 地図を動かしたり GPS の精度が変わったタイミングで、
    意図しない通信処理が実行された
    ○ GPS の精度はかなり頻繁に更新される
    ■ 通常の数百倍のリクエストにつながった
    23
    『GO』の事例: ”目に見えないバグ” がリリースされた

    View Slide

  24. © GO Inc. 24
    『GO』の事例: ”目に見えないバグ” がリリースされた
    ● コードレビューで気づけなかったのか?
    ○ 指摘がされていたが、修正されないまま Approve されマージされた
    ● QA で気づけなかったのか?
    ○ 現状の QA メンバーの規模ではサーバへの負荷にはならなかった
    ○ 通信回数の確認までは行っていなかった
    ● そもそも開発段階で気づけなかったのか?
    ○ シミュレータでは再現しづらいバグで気づけなかった
    バグは様々な工程をすり抜けてリリースされてしまう…!

    View Slide

  25. © GO Inc.
    ● 「目に見えない」ということが発見の障壁となった
    ○ 目に見えるようにすれば気づきやすくなるのでは?
    ● どれくらい通信されているかを可視化するデバッグモードを開発した
    ○ 各 API がどれくらいリクエストされているかを一覧表示させる
    ○ 前回のバージョンと比較して大幅な変化がないかを確認
    25
    『GO』の事例: ”目に見えないバグ” に対する再発防止策

    View Slide

  26. © GO Inc. 26
    『GO』の事例: ”目に見えないバグ” に対する再発防止策
    完璧な対応にはならないかもしれないが
    チームメンバーと再発防止策を検討して、すぐに対処する動きが大切

    View Slide

  27. © GO Inc. 27
    まとめ

    View Slide

  28. © GO Inc. 28
    まとめ
    ● 『GO』で起きた障害をもとに耐障害性の高いアプリ設計を検討した
    ● メンテナンスモードの設計
    ○ サーバ / DB に依存しない状態管理
    ○ 障害時と定期メンテナンス時では設計手法に差がある
    ● 強制アップデート機能の設計
    ○ アップデートの要求は起動直後が理想
    ○ ユーザにアップデートを促すためにうまく誘導する
    ● 根本的な原因の追究と対策
    ○ 同じ過ちを繰り返さぬようチームメンバーと対策を検討 & すぐ実行

    View Slide

  29. © GO Inc. 29
    さいごに・・・
    メンテナンスモードや強制アップデート機能が
    期待した動きをするか今一度確認を!
    障害はいつ起きるか予測できないので
    もし実装していない場合は早めの導入を検討しましょう

    View Slide

  30. © GO Inc. 30
    お知らせ

    View Slide

  31. © GO Inc. 31
    タクシーアプリ『GO』の開発を一緒にしませんか
    https://hrmos.co/pages/
    goinc/jobs

    View Slide

  32. © GO Inc. 32
    後夜祭 iOSDC Japan 2023 のご参加お待ちしています
    2023年09月26日 19:00 ~ 20:30
    https://hey.connpass.com/event/290854/

    View Slide

  33. 文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください。
    © GO Inc.

    View Slide