イベントアーキテクチャ
イベントアーキテクチャ(EDA)
1)イベントとは何ですか、そしてなぜEDA
イベント-ドメイン内で既に発生している変更のない事実("PlayerVerified"、 "PaymentCaptured')。EDAは、これらの事実の公表とそれらに対する反応に関する統合を構築します:- サービスの弱い接続性、
- 消費者を独立してスケーリングする、
- 投影の再生/再配置、
- 透明な監査。
EDAは同期APIをキャンセルせず、クロスサービスの依存関係を非同期レイヤーに取り込むことでそれらを補完します。
2)イベントタイプ
ドメイン:重要なビジネス事実(注文、ボーナス付与)。
統合:「スナップショット「/外部システムの変更(UserUpdated、 WalletBalanceChanged)。
技術:ライフサイクルとテレメトリー(Heartbeat、 PipelineFailed)。
コマンド(イベントではなく近く):「do X」 (CapturePayment)命令。
推奨事項:ドメインイベントはプライマリです。統合は特定の消費者のための投影によって形成される。
3)イベント契約とスキーマ
Схема: Avro/Protobuf/JSONスキーマ+スキーマレジストリ;互換性戦略:消費者の進化のための'BACKWARD'、重要なトピックの'FULL'。
CloudEvents (id、 source、 type、 time、 subject、 datacontenttype)-均一なヘッダー。
必須メタデータ:'event_id' (ULID/UUID)、 'occurious_at'、 'producer'、 'schema_version'、 'correlation_id'/'causation_id'、 'idempotency_key'。
バージョン管理:add-onlyフィールド、名前変更/セマンティックブレークの禁止;新しいタイプ-新しいテーマ/タイプ。
json
{
"type":"record","name":"PaymentCaptured","namespace":"events. v1",
"fields":[
{"name":"event_id","type":"string"},
{"name":"occurred_at","type":{"type":"long","logicalType":"timestamp-micros"}},
{"name":"payment_id","type":"string"},
{"name":"amount","type":{"type":"bytes","logicalType":"decimal","precision":18,"scale":2}},
{"name":"currency","type":"string"},
{"name":"player_id","type":"string"}
]
}
4)配達、順序および一貫性
default→handler idempotencyとして少なくとも1回は必要です。
注文:パーティー(Kafka)またはキュー(RabbitMQ)内で保証されていますが、後退によって壊れる可能性があります。イベントキーは、順序のドメイン微粒('player_id'など)を反映する必要があります。
一貫性:お金/ローンのために-雑誌/サガ/報酬を通じてのみ;LWWを避ける。
読み取りモデル:投影とキャッシュは最終的には「、更新中」……を表示し、厳密なパスにRNOT戦略を使用します。
5) Outbox/受信トレイのCDC
Outbox:サービスは、データベースとアウトボックステーブルに1つのトランザクション→ワーカーがバスに発行する事実を書き込みます。
受信トレイ:重複除外の処理結果を含む消費者ストア'event_id'。
CDC (Change Data Capture):データベース(binlog/WAL)からバスへの変更をフローし、アプリケーションの変更なしに統合を構築します。
Idempotency: 'idempotency_key'/'event_id'で処理し、修正されるまで外部の世界を変更しません。
6) CQRS○イベントソーシング
CQRS:別々の書き込みモデルと読み取り予測;投影はイベントから構築され、遅れを取ることができます。
イベントソーシング:集計状態=イベントのロールアップ。長所:完全な監査/再生;cons:マイグレーション/スキーム/スナップショットの複雑さ。
練習:ES-どこでもではなく、歴史と報酬が重要です。CQRS-ほとんどの場合EDAで。
7)サガ: オーケストレーションと振付
オーケストレーション:コーディネーターはコマンドを送信し、応答イベントを待ちます。複雑なプロセス(KYC→Deposit→Bonus)に便利です。
振付:サービスはお互いのイベントに反応します。簡単だが追跡しにくい。
補償とステップの期限を常に定義します。
8)トポロジーデザイン(Kafka/RabbitMQ)
カフカ(Kafka
ドメインイベントごとのトピック:'支払い。キャプチャされました。v1'、'プレイヤー。確認しました。v1'。
パーティションキー:'player_id'/'wallet_id'-注文が重要です。
'replication。factor=3'、'min。insync。replicas=2'、producer' acks=all'。
保持:時間によって(例えば。7-90日)および/または圧縮(キーによる最後の状態)。
バックオフでの再試行とDLQのトピック。
RabbitMQ
取引所:'トピック'/'直接'、ルーティングキー'支払い。キャプチャされました。v1'。
広いファンアウトの場合-'topic'+複数のキュー;RPC/コマンドの場合-キューを分離します。
HAのクォーラムキュー;TTL+リトレイのデッドレター交換。
9)観測可能性とSLO EDA
SLI/SLO:- エンドツーエンドのレイテンシ(occurred_at→処理済み):p50/p95/p99。
- 遅れ/年齢:消費者の遅れ(カフカの消費者の遅れ、ウサギのバックログの年齢)。
- スループット発行/処理。
- DLQレートとリピートの割合。
- ビジネストランザクションの成功(例:「デポジット確認≤ 5c」)。
- 'trace_id'/'correlation_id' (OTel)によるイベントの相関。
- アライメント→メトリックからのインスタンス。
- ダッシュボード「Producer→Broker→Consumer」でバーンレートのアラートが表示されます。
10)再生、保持およびbackfill
リプレイして投影を再構築/修正するバグ:新しい投影/スペースにドライブし、読み取りを切り替えます。
保持:法的/ビジネス要件(GDPR/PCI);機密フィールド-暗号化および/またはトークン化。
Backfill: 1つのオフテーマ/キュー、prodを抑制することを避けるために明確なRPS制限。
11)安全性とコンプライアンス
内部クライアントのためのTLS in-transit、 mTLS。
認可:トピックごと/取引所ごとのACL;名前空間/vhostを介したマルチテンシー。
PII:イベントのフィールドを最小化します。エンベロープメタデータは別途、ペイロードは必要に応じて暗号化されます。
イベントへのアクセスを監査し、「全力」キーを禁止します。
Retention and Right to Delete (GDPR)ポリシー:データ参照または墓石イベントを保存し、投影に削除します。
12) EDAでのテスト
契約テスト:消費者はスキーム(消費者主導)に対する期待を検証します。
リプレイテスト:新しいハンドラ/スキーマのバージョンで履歴サンプリングを実行します。
カオスシナリオ:ブローカーの遅延/損失、ノードドロップ、コンシューマラグ→SLOが残ります。
CIの煙:時間テーマの短いエンドツーエンドのパイプライン。
13) 「CRUD統合→EDA」の移行"
1.ドメインの事実を特定します。
2.ソースサービスにアウトボックスを埋め込む。
3.最小限のドメインイベントを公開し、1-2プロジェクションを接続します。
4.ポイント同期インテグレーションを徐々に無効にし、サブスクリプションに置き換えます。
5.スキーマレジストリと互換性ポリシーを入力します。
6.フィールドを持つアドオンイベントを拡張します。breaks-新しいタイプのみ。
14)アンチパターン
イベント=「DTO API」(脂肪が多すぎ、内部モデルに依存)-消費者を破る。
スキーマレジストリと互換性の欠如-「壊れやすい」統合。
コードからのパブリッシングとデータベースへの書き込みはアトミックではありません(アウトボックスなし)-イベントを失います。
「どこでも正確に一度」-利益のない高価格。よりよい少なくとも一度+idempotency。
1つの「ユニバーサル」パーティションキー→ホットパーティション。
本番プロジェクションにまっすぐリプレイ-オンラインSLOを壊します。
15)実装チェックリスト(0-45日)
0-10日
ドメインイベントとそのキー(注文の微粒)を特定します。
スキーマレジストリを展開し、互換性戦略を承認します。
1-2サービスにoutbox/inboxを追加します。最小限のCloudEvents-envelope。
11-25日
リトライ/DLQ、バックオフ、ハンドラのidempotencyを入力します。
ダッシュボード:遅延/年齢/エンドツーエンド;バーンレートアラート。
イベントドキュメント(カタログ)、所有者およびスキーマレビュープロセス。
26-45日
最初の投影の再生/再配置;runbookの再生およびbackfill。
セキュリティポリシー(TLS、 ACL、 PII)、保持、GDPR手順。
ブローカーと消費者のための定期的な混乱とゲームの日。
16)成熟度の指標
ドメインイベントの100%はスキームによって記述され、登録されます。
Outbox/inboxはすべてのTier-0/1の生産者/消費者をカバーします。
SLO: p95エンド・ツー・エンドのレイテンシーと99% ≥ターゲット内の消費者のラグ。
リプレイ/バックフィルはダウンタイムなしで実行可能です。確認されたランブックがあります。
バージョン管理:新しいフィールド-壊れず;古い消費者は落ちることはありません。
セキュリティ:TLS+mTLS、トピックごとのACL、アクセスログ、PII/保持ポリシー。
17)ミニスニペット
カフカプロデューサー(信頼できる出版物、アイデア):properties acks=all enable. idempotence=true max. in. flight. requests. per. connection=1 compression. type=zstd linger. ms=5
消費者ハンドラ(idempotency、 pseudocode):
python if inbox. contains (event_id): return # dedup process (event) # side effects are deterministic inbox. commit(event_id) # atomically with side-effect commit_offset()
DLXによるRabbitMQの再試行(アイデア):
- 'queue: tasks'→on nack→DLX 'tasks。再試行してください。1m '(TTL=60s)→'tasks'に戻る;さらに'5m/15m'。
18)結論
EDAは、統合を明確な契約と管理の一貫性を備えたビジネス事実の流れに変えます。schemas+registry、 outbox/inbox、 order keys、 idempotent handlers、 SLOとobservability、安全な保持と再生。その後、イベントはスケーリング、分析、新機能のための「真実の源」になります。壊れやすい接続と夜間の移行はありません。