Upgrade to Pro — share decks privately, control downloads, hide ads and more …

疎結合でスキーマ駆動開発を実現するイベントバスの設計

 疎結合でスキーマ駆動開発を実現するイベントバスの設計

Platform Engineering Kaigi 2025 #PEK2025

Yoshiaki Ueda / bootjp
株式会社hacomono/基盤本部
プリンシパル分散システムエンジニア

株式会社hacomono所属のプリンシパル分散システムエンジニア。hacomonoではマイクロサービス化に向けた課題整理/設計/開発を担当。前職ではRaftを用いた分散ストレージを設計開発。プライベートではRaftを用いた分散KVSに関する技術同人誌の執筆を行ったり、趣味でパブリッククラウドの論文を読みブログにメモとして残している。

https://www.cnia.io/pek2025/sessions/e11d6f4d-eccf-47c5-95e9-f2664f5ab0c4/

Avatar for hacomono Inc.

hacomono Inc. PRO

September 18, 2025

More Decks by hacomono Inc.

Other Decks in Technology

Transcript

  1. Last Update 2022.03.16 Platform Engineering Kaigi 2025 Track A 15:15~15:45

    疎結合でスキーマ駆動開発を実現するイベントバスの設計
  2. 2 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  3. 3 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  4. 6 今日の発表する内容について • イベントバスがなぜ必要なのか ◦ APIの密結合における問題点 • 開発者が安心して利用できるイベントバスとはどういうものか ◦ スキーマ駆動でスキーマを信頼できる開発フロー

    ▪ スキーマの破壊的変更の検知 ▪ バリデーションロジックの共通化 ◦ 不正なイベントや実装ミスを防ぐ仕組み ◦ カスケード障害の抑制 • 「スキーマ駆動イベントバス」の段階的導入プロセスについて 本発表について
  5. 7 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  6. 8 @bootjp Yoshiaki UEDA 自己紹介 経歴(前略) ◦ 2018年~2021年: Supership株式会社  スマホ向け大量配信システムの開発/運用

     検索・検索連動広告 開発/運用 ◦ 2021年~2023年: 株式会社プレイド   大量配信システムのリプレース   分散システムの相談窓口 ◦ 2023年~2024年: btj.systems合同会社  Raftを用いた分散ストレージの研究/開発 ◦ 2024年~現在: 株式会社hacomono プリンシパル分散システムエンジニア 基盤本部にて共通基盤を設計/開発 株式会社hacomno プリンシパル分散システムエンジニア
  7. 9 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  8. 10 会員管理・予約・振替・キャンセル・決済・請求管理・売上管理・債権管理 入退館・EC・POS・本人認証カメラ・QRリーダー・ ・総合フィットネスクラブ ・ヨガ・ピラティス ・パーソナルジム ・24時間ジム フィットネスクラブ ・屋外運動場 ・屋内運動場

    ・体育館 ・水泳プール ・学校 ・レジャー施設 公共運動施設 ・Jリーグ(サッカー) ・Bリーグ(バスケットボール) ・野球チーム・サッカーチーム etc スポーツチーム ・スイミングスクール ・ダンス・バレエスクール ・ゴルフスクール ・テニススクール ・カルチャースクール ・空手・体操スクール ・サッカースクール 運動スクール ウェルネス施設の手続きをすべてデジタル化 ウェルネス産業を、新次元へ。
  9. 12 • hacomonoでは可用性が異なるコンポーネントが複数ある ◦ 特別に高い可用性が要求されるコンポーネント ▪ IoTデバイスと通信する入退館システム ▪ 予約システム ▪

    決済 ◦ 開発速度と可用性を両立のためサービスの分割を推進 ▪ 各サービス間でデータ連携をする • マルチプロダクト展開 ◦ 複数のプロダクトを展開し相互にデータを連携する 株式会社hacomonoについて
  10. 13 • hacomonoでは可用性が異なるコンポーネントが複数ある ◦ 特別に高い可用性が要求されるコンポーネント ▪ IoTデバイスと通信する入退館システム ▪ 予約システム ▪

    決済 ◦ 開発速度と可用性を両立のためサービスの分割を推進 ▪ 各サービス間でデータ連携をする • マルチプロダクト展開 ◦ 複数のプロダクトを展開し相互にデータを連携する 株式会社hacomonoについて
  11. 14 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  12. 15 密結合アーキテクチャとその問題点 • サービス同士がAPIを直接呼び合う世界の限界 ◦ サービスの数が増えるほど、経路の数は爆発的に増加 ◦ 開発者が他のサービス仕様を把握するコストの増大 ▪ →

    開発速度の低下 • API改修時の影響範囲が不明確に ◦ どのサービスがこのAPIを利用しているか明確ではない ◦ 「この変更はどこまで影響する?」 ▪ → 改修・デプロイへの恐怖 • メンテナンスでの計画停止が不可能に... なぜイベントバスが必要なのか
  13. 16 • hacomonoでは可用性が異なるコンポーネントが複数ある ◦ 特別に高い可用性が要求されるコンポーネント ▪ IoTデバイスと通信する入退館システム ▪ 予約システム ▪

    決済 ◦ 開発速度と可用性を両立のためマイクロサービス化を推進 • マルチプロダクト展開 ◦ 複数の製品ラインを展開し、各製品の情報を連携する なぜイベントバスが必要なのか ※エンドポイントは例で実際の構成とは異なります。
  14. 17 • hacomonoでは可用性が異なるコンポーネントが複数ある ◦ 特別に高い可用性が要求されるコンポーネント ▪ IoTデバイスと通信する入退館システム ▪ 予約システム ▪

    決済 ◦ 開発速度と可用性を両立のためマイクロサービス化を推進 • マルチプロダクト展開 ◦ 複数の製品ラインを展開し、各製品の情報を連携する なぜイベントバスが必要なのか ※エンドポイントは例で実際の構成とは異なります。
  15. 18 • hacomonoでは可用性が異なるコンポーネントが複数ある ◦ 特別に高い可用性が要求されるコンポーネント ▪ IoTデバイスと通信する入退館システム ▪ 予約システム ▪

    決済 ◦ 開発速度と可用性を両立のためマイクロサービス化を推進 • マルチプロダクト展開 ◦ 複数の製品ラインを展開し、各製品の情報を連携する なぜイベントバスが必要なのか とても厳しい
  16. 19 目指すべきは疎結合な世界 • ❌ NG ◦ 「ある出来事」が起きた際に呼び出すAPIを把握する ◦ 仕様変更の度にAPI呼び出し元に影響がないか確認 ◦

    APIの呼び出しもとを把握する • ✅ OK ◦ サービスは自分に関連する「ある出来事」だけ知っていれば良い ▪ Publish/Subscribe パターン ◦ 「ある出来事のイベント」を送ったらその後のことに関与しない ▪ fire-and-forgetパターン なぜイベントバスが必要なのか
  17. 22 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  18. 23 ここまでの話 • ✅ 解決済み ◦ サービスがAPIの依存関係の管理 ▪ イベントとして「発生した出来事」を記録する ▪

    「発生した出来事」に関心があるサービスがSubscribeする ◦ サービスがAPIのエンドポイントを管理する ▪ イベントバスのエンドポイントだけ知っていればよい ◦ 計画メンテナンスが可能に ▪ 呼び出し先がメンテナンス中であっても順次再送される 開発者が安心して利用できるイベントバスとは
  19. 24 ▶ まだやるべきことがある • 互換性のないスキーマ変更を発生させない仕組み • アプリケーション毎に異なるバリデーションロジックを減らす • イベントバスから送られるイベントを正規のものに限定する •

    開発者が開発環境と本番環境を間違えてもイベントを弾く • 開発者のミスによるイベントのループや再送による障害を抑制する 開発者が安心して利用できるイベントバスとは
  20. 25 互換性のないスキーマ変更を発生させない仕組み • ❌ NG ◦ フィールドの削除 ◦ フィールドの型変更 ◦

    イベントの削除 ◦ 🤔「この変更って安全かな?」 • ✅ OK ◦ CIによって破壊的変更を不可能にする ◦ 😁「CIをパスしているので安全」 開発者が安心して利用できるイベントバスとは
  21. 26 開発者が安心して利用できるイベントバスとは アプリケーション毎に異なるバリデーションロジックを減らす • より柔軟に、詳細にイベントをコントロールする • ❌ NG ◦ あるサービスではUserIDはUUID

    ◦ あるサービスではUserIDはハッシュ値 • ✅ OK ◦ UserIDはUUID形式 ◦ 施設説明文は最大256文字 ◦ 電話番号は国際電話番号形式(+81) ◦ URLはRFC 3986の形式
  22. 27 イベントバスから送られるイベントを正規のものに限定する • ❌ NG ◦ 攻撃者によるイベントを受け入れてしまう ◦ 開発環境から本番環境に送信可能 ◦

    本番環境から開発環境に送信可能 • ✅ OK ◦ 署名検証に成功したイベントのみ配信 ◦ 異なる環境からのイベントをブロック ◦ 😃「イベントバスからのイベントは信頼できる」 開発者が安心して利用できるイベントバスとは
  23. 28 開発者のミスによるイベントのループや再送による障害を抑制する • ❌ NG ◦ ループしたイベントによるサービスダウン ◦ 同一イベントの大量発行によるサービスダウン ◦

    大量イベント発生によるカスケード障害 • ✅ OK ◦ 同一の送信元の同一イベントは拒否 ◦ RateLimitによる送信間隔制御(予定) ◦ 実装ミスでも障害を抑制する仕組みに 開発者が安心して利用できるイベントバスとは
  24. 29 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  25. 37 今日の発表の流れ • 本発表について • 自己紹介 • 株式会社hacomonoについて • なぜイベントバスが必要なのか

    • 開発者が安心して利用できるイベントバスとは • 「スキーマ駆動イベントバス」 • イベントバスの段階的導入プロセスについて • まとめ
  26. 43 まとめ • サービス間のAPIの呼び出しは依存関係や影響範囲の把握が困難 ◦ → イベントバスを導入し解決 • 開発者が安心して開発できる仕組みへ ◦

    破壊的変更ができないスキーマ管理の仕組み ◦ バリデーションロジックの共通化 ◦ 不正なイベントを弾く仕組み ◦ 過剰なイベントを抑制する仕組み • 段階的な導入 ◦ 新規のプロダクトの非同期化できる処理から導入を開始
  27. 45 出典 • Protocol Buffers Documentation: ◦ https://protobuf.dev/ • Buf

    CLI: ◦ https://buf.build/product/cli • Protovalidate: ◦ https://protovalidate.com/ • Fire-and-Forget - Enterprise Integration Patterns: ◦ https://www.enterpriseintegrationpatterns.com/patterns/conversation/ FireAndForget.html • JSON Web Tokenの概要 - jwt.io ◦ https://www.jwt.io/ja/introduction#when-to-use-json-web-tokens • Pattern: Saga ◦ https://microservices.io/patterns/data/saga.html