Slide 1

Slide 1 text

Last Update 2022.03.16 Platform Engineering Kaigi 2025 Track A 15:15~15:45 疎結合でスキーマ駆動開発を実現するイベントバスの設計

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

4 本発表について

Slide 5

Slide 5 text

5 本発表について

Slide 6

Slide 6 text

6 今日の発表する内容について ● イベントバスがなぜ必要なのか ○ APIの密結合における問題点 ● 開発者が安心して利用できるイベントバスとはどういうものか ○ スキーマ駆動でスキーマを信頼できる開発フロー ■ スキーマの破壊的変更の検知 ■ バリデーションロジックの共通化 ○ 不正なイベントや実装ミスを防ぐ仕組み ○ カスケード障害の抑制 ● 「スキーマ駆動イベントバス」の段階的導入プロセスについて 本発表について

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

8 @bootjp Yoshiaki UEDA 自己紹介 経歴(前略) ○ 2018年~2021年: Supership株式会社  スマホ向け大量配信システムの開発/運用  検索・検索連動広告 開発/運用 ○ 2021年~2023年: 株式会社プレイド   大量配信システムのリプレース   分散システムの相談窓口 ○ 2023年~2024年: btj.systems合同会社  Raftを用いた分散ストレージの研究/開発 ○ 2024年~現在: 株式会社hacomono プリンシパル分散システムエンジニア 基盤本部にて共通基盤を設計/開発 株式会社hacomno プリンシパル分散システムエンジニア

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

10 会員管理・予約・振替・キャンセル・決済・請求管理・売上管理・債権管理 入退館・EC・POS・本人認証カメラ・QRリーダー・ ・総合フィットネスクラブ ・ヨガ・ピラティス ・パーソナルジム ・24時間ジム フィットネスクラブ ・屋外運動場 ・屋内運動場 ・体育館 ・水泳プール ・学校 ・レジャー施設 公共運動施設 ・Jリーグ(サッカー) ・Bリーグ(バスケットボール) ・野球チーム・サッカーチーム etc スポーツチーム ・スイミングスクール ・ダンス・バレエスクール ・ゴルフスクール ・テニススクール ・カルチャースクール ・空手・体操スクール ・サッカースクール 運動スクール ウェルネス施設の手続きをすべてデジタル化 ウェルネス産業を、新次元へ。

Slide 11

Slide 11 text

10,000店舗・施設での導入実績 ヨガ・ピラティス パーソナルジム 24時間ジム 総合スポーツクラブ 運動スクール プロスポーツ(サッカー・バスケ) 公共運動・学校施設 ゴルフ サウナ・エステ コワーキング

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

15 密結合アーキテクチャとその問題点 ● サービス同士がAPIを直接呼び合う世界の限界 ○ サービスの数が増えるほど、経路の数は爆発的に増加 ○ 開発者が他のサービス仕様を把握するコストの増大 ■ → 開発速度の低下 ● API改修時の影響範囲が不明確に ○ どのサービスがこのAPIを利用しているか明確ではない ○ 「この変更はどこまで影響する?」 ■ → 改修・デプロイへの恐怖 ● メンテナンスでの計画停止が不可能に... なぜイベントバスが必要なのか

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

18 ● hacomonoでは可用性が異なるコンポーネントが複数ある ○ 特別に高い可用性が要求されるコンポーネント ■ IoTデバイスと通信する入退館システム ■ 予約システム ■ 決済 ○ 開発速度と可用性を両立のためマイクロサービス化を推進 ● マルチプロダクト展開 ○ 複数の製品ラインを展開し、各製品の情報を連携する なぜイベントバスが必要なのか とても厳しい

Slide 19

Slide 19 text

19 目指すべきは疎結合な世界 ● ❌ NG ○ 「ある出来事」が起きた際に呼び出すAPIを把握する ○ 仕様変更の度にAPI呼び出し元に影響がないか確認 ○ APIの呼び出しもとを把握する ● ✅ OK ○ サービスは自分に関連する「ある出来事」だけ知っていれば良い ■ Publish/Subscribe パターン ○ 「ある出来事のイベント」を送ったらその後のことに関与しない ■ fire-and-forgetパターン なぜイベントバスが必要なのか

Slide 20

Slide 20 text

20 目指すべきは疎結合な世界 なぜイベントバスが必要なのか

Slide 21

Slide 21 text

21 イベントバスの導入 ● サービスはイベントバスのエンドポイントにイベントを送信する ● あるイベントを受信したいサービスはイベントをSubscribeする なぜイベントバスが必要なのか

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

23 ここまでの話 ● ✅ 解決済み ○ サービスがAPIの依存関係の管理 ■ イベントとして「発生した出来事」を記録する ■ 「発生した出来事」に関心があるサービスがSubscribeする ○ サービスがAPIのエンドポイントを管理する ■ イベントバスのエンドポイントだけ知っていればよい ○ 計画メンテナンスが可能に ■ 呼び出し先がメンテナンス中であっても順次再送される 開発者が安心して利用できるイベントバスとは

Slide 24

Slide 24 text

24 ▶ まだやるべきことがある ● 互換性のないスキーマ変更を発生させない仕組み ● アプリケーション毎に異なるバリデーションロジックを減らす ● イベントバスから送られるイベントを正規のものに限定する ● 開発者が開発環境と本番環境を間違えてもイベントを弾く ● 開発者のミスによるイベントのループや再送による障害を抑制する 開発者が安心して利用できるイベントバスとは

Slide 25

Slide 25 text

25 互換性のないスキーマ変更を発生させない仕組み ● ❌ NG ○ フィールドの削除 ○ フィールドの型変更 ○ イベントの削除 ○ 🤔「この変更って安全かな?」 ● ✅ OK ○ CIによって破壊的変更を不可能にする ○ 😁「CIをパスしているので安全」 開発者が安心して利用できるイベントバスとは

Slide 26

Slide 26 text

26 開発者が安心して利用できるイベントバスとは アプリケーション毎に異なるバリデーションロジックを減らす ● より柔軟に、詳細にイベントをコントロールする ● ❌ NG ○ あるサービスではUserIDはUUID ○ あるサービスではUserIDはハッシュ値 ● ✅ OK ○ UserIDはUUID形式 ○ 施設説明文は最大256文字 ○ 電話番号は国際電話番号形式(+81) ○ URLはRFC 3986の形式

Slide 27

Slide 27 text

27 イベントバスから送られるイベントを正規のものに限定する ● ❌ NG ○ 攻撃者によるイベントを受け入れてしまう ○ 開発環境から本番環境に送信可能 ○ 本番環境から開発環境に送信可能 ● ✅ OK ○ 署名検証に成功したイベントのみ配信 ○ 異なる環境からのイベントをブロック ○ 😃「イベントバスからのイベントは信頼できる」 開発者が安心して利用できるイベントバスとは

Slide 28

Slide 28 text

28 開発者のミスによるイベントのループや再送による障害を抑制する ● ❌ NG ○ ループしたイベントによるサービスダウン ○ 同一イベントの大量発行によるサービスダウン ○ 大量イベント発生によるカスケード障害 ● ✅ OK ○ 同一の送信元の同一イベントは拒否 ○ RateLimitによる送信間隔制御(予定) ○ 実装ミスでも障害を抑制する仕組みに 開発者が安心して利用できるイベントバスとは

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

30 「スキーマ駆動イベントバス」 GitHub Actions CI/CD Pipeline

Slide 31

Slide 31 text

31 「スキーマ駆動イベントバス」 互換性のないスキーマ変更を発生させない仕組み ● Protocol Bufferを用いたスキーマ管理 ○ シリアライズ形式はJSON ● Buf CLIを用いたCIによる破壊検知 https://buf.build/product/cli

Slide 32

Slide 32 text

32 「スキーマ駆動イベントバス」 アプリケーション毎に異なるバリデーションロジックを減らす ● protovalidateを用いたバリデーションロジックの共通化 https://protovalidate.com/

Slide 33

Slide 33 text

33 「スキーマ駆動イベントバス」 イベントバスから送られるイベントを正規のものに限定する ● サービスと環境毎に異なる非対称鍵を用いイベントをJWT署名する ○ サービスA 開発環境 ■ 開発用秘密鍵の署名 -> 開発用の公開鍵での検証 ○ サービスA 本番環境 ■ 本番用秘密鍵の署名 -> 本番用の公開鍵での検証

Slide 34

Slide 34 text

34 「スキーマ駆動イベントバス」 開発者のミスによるイベントのループや再送による障害を抑制する ● DynamoDBに送信元とEventIDの組み合わせを保存 ○ 重複するイベントが発行された場合拒否する ○ カスケード障害の抑制が目的 ■ Exactly onceは保証しない

Slide 35

Slide 35 text

35 「スキーマ駆動イベントバス」 全体アーキテクチャ図

Slide 36

Slide 36 text

36 「スキーマ駆動イベントバス」 全体アーキテクチャ図 SDK SDK

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

38 段階的導入プロセス

Slide 39

Slide 39 text

39 段階的導入プロセス

Slide 40

Slide 40 text

40 段階的導入プロセス

Slide 41

Slide 41 text

41 段階的導入プロセス

Slide 42

Slide 42 text

42 段階的導入プロセス https://speakerdeck.com/hacomono/job-platform-powered-by-aws-step-functions

Slide 43

Slide 43 text

43 まとめ ● サービス間のAPIの呼び出しは依存関係や影響範囲の把握が困難 ○ → イベントバスを導入し解決 ● 開発者が安心して開発できる仕組みへ ○ 破壊的変更ができないスキーマ管理の仕組み ○ バリデーションロジックの共通化 ○ 不正なイベントを弾く仕組み ○ 過剰なイベントを抑制する仕組み ● 段階的な導入 ○ 新規のプロダクトの非同期化できる処理から導入を開始

Slide 44

Slide 44 text

44 hacomonoはエンジニアを募集しています 事業成長を加速させる深い問題解決ができるエンジニアを探しています ● 技術の仕組みと背景の深い理解 ● 技術のトレードオフの把握とその限界に挑戦 ● ビジネスニーズに合わせた最適な問題解決能力 挑戦できる環境 ● プラットフォームエンジニアリングを推進している ● マイクロサービス、マルチプロダクト化を推進 ● 高可用性・高信頼性なシステムの設計・実装に挑戦できる

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

ご清聴いただき ありがとうございました 46