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

メッセージとイベントを中核に置いたシステム設計の有用性について

 メッセージとイベントを中核に置いたシステム設計の有用性について

現代のシステム設計において、メッセージとイベント駆動のアプローチは、即応性、スケーラビリティ、耐障害性を実現するための重要な要素です。本セッションでは、その有用性と具体的な適用方法について解説します。

かとじゅん

May 21, 2024
Tweet

More Decks by かとじゅん

Other Decks in Programming

Transcript

  1. 自己紹介 現職は Chatworkのテックリード。 Scalaや DDDを駆使した開発に 12年以上携 わってきました。技術戦略の策定から高難度な技術案件のサポートまで、幅広 く担当しています。 執筆 WEB+DB

    PRESS Vol.126 - 21周年記念エッセイ 今も読み続ける 1冊の本 レビュー エリックエヴァンスのドメイン駆動設計 Akka実践バイブル ドメイン駆動設計入門 良いコード/悪いコードで学ぶ設計入門 WEB+DB PRESS Vol.132 - 特集 1 オブジェクト指向神話からの脱却 趣味は Rust。最近 CQRS/Event Sourcing用ライブラリを TS,Go,Rust,JVM向 けに実装してます。 twitter: j5ik2o github: j5ik2o ©2024 Junichi Kato, Chatwork Inc 1 / 49
  2. なぜメッセージとイベントに注目するのか ユーザー目線では、即応性(システムがいつでも使用可能であること)は「当たり前品質」 この「当たり前品質」を確保しつつ、プロダクトとしての「魅力的品質」を提供することが求められる 即応性 を実現するためには、スケーラビリティ (弾力性 )と耐障害性が必要 これらを実現するには、メッセージ駆動 が必要 メソッド駆動のアーキテクチャだけでは限界がある

    今回は 非同期なメッセージング と イベント駆動アーキテクチャ にフォーカスする ユーザの要求の変化 ノード数は数十台から数百・数千コアへ レスポンスタイムは秒からミリ秒オーダーに ダウンタイムは数時間から限りなくゼロに 処理対象のデータ規模はギガからペタへ (そもそも終わり がない ) 形 ⼿段 値 即応性 拡張可能 拡張可能 耐障害性 メッセージ駆動 弾⼒性 リアクティブシステム ©2024 Junichi Kato, Chatwork Inc 1 / 49
  3. FYI: メッセージのサブセット コマンド (EIP: Command Message) コマンドリクエスト : 受信者へ の命令や指示。コマンドリク

    エスト名がメソッド、パラメ ータが引数に対応 コマンドレスポンス : コマン ド・リクエストに対応する返 信。戻り値に相当するが、こ れも非同期にメッセージ送信 しているに過ぎない イベント (EIP: Event Message) 後述 概念図 Message CommandRequest id: ULID aggregateId: AggregateId replyTo: ActorRef CommandResponse id: ULID PostMessage content: Content senderId: UserAccountId PostMessageSucceeded messageId: MessageId PostMessageFailed error: PostMessageError Event id: ULID aggregateId: AggregateId occurredAt: Instant sequenceNumber: Long MessagePosted content: Content senderId: UserAccountId ©2024 Junichi Kato, Chatwork Inc 1 / 49
  4. 「世界は事実の総体である」 ウィトゲンシュタインの哲学から 「 1.1 世界は、事実 の総体である。事物 の総体ではない。 」 世界が事物の総体であり、事実の総体ではないとしたら、 「ここにリンゴがあ

    る」 という事実すらも世界には含まれなくなってしまう つまり「事実」が中心的な要素である。事物はその「事実」の一部として存在す る。 ドメイン分析のフェーズにおいても以下の視点が役立つ 事実 : ドメインイベント 事物 : ドメインイベントに関連するドメインモデル ドメインイベントはドメイン分析のツールとして使える ©2024 Junichi Kato, Chatwork Inc 1 / 49
  5. メッセージの同期通信と非同期通信の比較 メッセージを送信するに当たって、両者間が同期か、非同期かの違い。 同期通信では、両者が同時に通信の準備ができている必要がある 非同期通信では、送信者は受信者の準備がでているかに関係なく送信できる ※同期通信には、相手に送信できたかわかるためのタイマーが必要になる。 同期通信 送信者 受信者 タスクを依頼する ⼀定時間

    返信を待つ タスクの完了を通知する 他のタスクを実⾏する ⾮同期通信 送信者 受信者 タスクを依頼する 依頼だけを 受け取れる 他のタスクを実⾏する タスクの完了を通知する 完了通知を いつ受け取ってもいい 返信時の処理 ©2024 Junichi Kato, Chatwork Inc 1 / 49
  6. フロー制御を考慮したメッセージの送受信 送信レートを調節して受信側に負担が掛からないようにするプロセスのこと=フロー制御 送信側は受信側からの要求で流量を調整する。送信側にて背圧制御 (バックプレッシャ )がかかる バックプレッシャなし 送信者 受信者 メッセージを送信 メッセージを送信

    メッセージを送信 処理能⼒オーバー 返信を返す 下流が遅いとき 送信者 受信者 1要素を要求 メッセージを送信 返信を返す 下流が早いとき 送信者 受信者 2要素を要求 メッセージを送信 メッセージを送信 返信を返す 返信を返す ©2024 Junichi Kato, Chatwork Inc 1 / 49
  7. 透過的リモーティング (Transparent Remoting) 送信元がリモートかローカルかは区別しない 受信側プロセスが送信元がリモートかローカルかを区別しない仕組み。 リモートからのメッセージもあたかもローカルから届いたメッセージをハンドラに渡される。メッセージに付与される送信元 の replyToはローカルの宛先のように見えるが、実際にはリモートと接続可能なプロキシが生成される。 replyToにメッセージ を送ることができる。

    // replyToはリモート上のクライアントプロキシーに該当する def greeterBehavior: Behavior[Message] = Behaviors.receive { (context, message) => message match { case Greet(who, replyTo) => // replyTo: ActorRef[Greeted] // メッセージを処理して応答 replyTo ! Greeted(who) // replyTo.tell(Greeted.of(who)); Behaviors.same // ... } } ©2024 Junichi Kato, Chatwork Inc 1 / 49
  8. メッセージはマルチスレッディングと RPCを統合する 位置透過性( Location Transparency) 透過的リモーティング (Transparent Remoting) によって、マルチスレッディングと RPCの区別がなくな

    り、クラスター上にあるすべてのコンピュータがローカル コンピュータのように扱えるようになる。 スケーリングにおけるスケールアップもスケールアウト も、すべてメッセージによって区別することなく利用可能 になり、コードを大幅に変更する必要がなくなる。 今日は詳しく話さないが、この特徴をうまく使ってコンテ キスト境界の見直しのハードルを下げることができる ©2024 Junichi Kato, Chatwork Inc 1 / 49
  9. イベントのアーキテクチャ上の有用性 実装上でも有用! イベントとは、システム内で発生した出来事を表すメッセージの一種。以下のような特徴を持ちます。 状態変化の通知 (Pub/Sub) イベントは、システムの状態が変化したことを 他のコンポーネントに通知するために 使われる 例えば、ユーザーがボタンをクリックした、新しいデータが到着した、タイマーが期限に達したなどの出来事が、イベ ントとして表現される

    不変の事実記録と状態構築 (Event Sourcing) イベントは、システム内で起きた具体的な事実を記録する。これらのイベントは変更不可能で、一度発生したら取り消 すことはできない システムの状態はこれらの事実に基づいており、イベントの集合を使って任意の時点でのシステムの状態を再構築でき る。これにより、 システムの現在の状態が過去の事実に基づいていることが保証される Pub/Subと Event Sourcingは、関係性が深いため混同しやすいが目的が異なる。 ©2024 Junichi Kato, Chatwork Inc 1 / 49
  10. State Sourcing + Pub/Sub Pros シンプルな実装 : 既存のデータベースと Pub/Subシステムを使用することで、比較的簡単に実装できる 直感的なデータモデル

    : 現在の状態をそのままデータベースに保存するため、データモデルが直感的 Cons 2フェーズコミットの問題 : 分散トランザクションをサポートしないため、一貫性の確保が難しくなる ©2024 Junichi Kato, Chatwork Inc 1 / 49
  11. Event Sourcing + Pub/Sub Pros 一貫性の向上 : 同一トランザクションで処理する必要がないため、データの一貫性をより確実に保てる 過去の状態の追跡が容易 :

    すべてのイベントを保存するため、過去の状態を容易に再現できる スケーラビリティ : 非同期処理により、システム全体のスケーラビリティが向上する Cons 複雑な実装 : イベントストアやスナップショットの管理が必要なため、実装が複雑になる (ツールである程度はカバーで きるようになっている ) ©2024 Junichi Kato, Chatwork Inc 1 / 49
  12. FYI: 実装のためのツール Event Store Adatpor Amazon DynamoDB を Event Store化するためのライブラリ。スケーラビリティと耐障害性を両立

    アクターモデルに限らず、従来のオブジェクトモデルでも Event Sourcingを実現可能 対応言語 : Go, Rust, Scala, Kotlin, Java, TypeScript 実施の実装例はこちら Akka Pekko Axon Proto.Actor ©2024 Junichi Kato, Chatwork Inc 1 / 49
  13. 参考資料 Reactive Desgin Patterns マイクロサービスアーキテクチャ Awesome Domain-Driven Design Awesome Elixir

    and CQRS 現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法 ©2024 Junichi Kato, Chatwork Inc 1 / 49