API構築の基礎を学んだ。QConは、開発者コミュニティにおける知識とイノベーションの普及を促進することで、ソフトウェア開発に力を与える。実務者主導のカンファレンスであるQConは、チーム内のイノベーションに影響を与える技術チームのリーダー、アーキテクト、エンジニアリングディレクター、プロジェクトマネージャー向けにデザインされている。Sheehy氏は、人工知能ハイプ時代における責任ある開発者としてのあり方について、洞察に富んだ開会基調講演をした。Grizzanti氏が、「スタッフ・プラス」への道と、それを「科学」というより「芸術」としてとらえ、芸術を創作することとソフトウェアを創作すること、そして組織のダイナミクスに対処することの類似性について語っている。Codeを採用する:確認するべき6つの適性LCNC(ローコード/ノーコード)プラットフォームは、プログラマーだけでなくプログラマーでなくても、最小限のコーディングとワンクリックのデプロイメントで、アプリケーションソフトウェアを開発できるよう設計されている。ドラッグ&ドロップ方式のインターフェースなどを利用することで、開発・デプロイメントプロセスを簡素化し、効率的なアプリケーション開発とデプロイメントを実現する。pattern.原文(投稿日:2021/02/25)へのリンクマイクロサービスに移行するときに最初に気付くのは、個々のサービスが独立して存在するわけではないということです。目標は、相互作用をできるだけ少なくして疎結合の独立したサービスを作成することですが、あるサービスが別のサービスが所有する特定のデータセットを必要とするか、私たちのビジネスの領域でのオペレーションの合致する成果を達成するために複数のサービスが協調して動作する必要があります。変更データキャプチャを介して実装されるOutboxパターンは、マイクロサービス間のデータ交換の関心事に対処する実証済みのアプローチです。ような複雑なプロトコルを必要とせずに結果整合性のあるデータ交換を実現します。実装する方法を探求したいと思います。1つの一般的な例は、複数の部分で構成される旅行を予約する場合です。すべての航程と宿泊施設を一緒に予約するか、いずれもしないか。Sagaは、このような包括的なビジネストランザクションを、参加しているサービスによって実行される一連の複数のローカルデータベーストランザクションに分割します。障害が発生した場合に包括的なビジネストランザクションを「ロールバック」するために、Sagaは補償トランザクションの考えに依存しています。以前に適用された各ローカルトランザクションは、以前に行われた変更の反転を適用する別のトランザクションを実行することによって「元に戻す」ことができなければなりません。Sagaは新しい概念では決してありません。’87のSagas論文で論じました。示されているように、最近人気が高まっています。Sagasは、特により長い時間を要するトランザクションフローの実装に適しています。これは、通常ACIDセマンティクスでは対処できません。新しい注文書が注文サービスに送信されると、他の2つのサービスを含めて次のフローが実行されます。(1人の顧客の保留中の注文が特定のしきい値を超えることを望まないため)。顧客の与信限度額が$500で、価格が$300の新しい注文が入った場合、この注文は現在の限度額に収まり、残りの限度額は$200になります。与信限度額の確認に成功した場合は、支払いサービスを介して注文の支払いを要求する必要があります。(これはここで説明するプロセスの一部ではありません)。状態に移行する前に、以前に割り当てられた与信限度額を再度解放する必要があります。分散Sagaを実装するには、コレオグラフィーとオーケストレーションの2つの一般的な方法があります。コレオグラフィーアプローチでは、参加している1つのサービスが、ローカルトランザクションを実行した後、次のサービスにメッセージを送信します。オーケストレーションでは、参加者を次々に呼び出す1つの調整サービスがあります。Régo氏によるこの投稿を参照してください)。個人的には、オーケストレーションアプローチを好んでいます。現在のステータスを取得するために照会できる1つの中心的な場所を定義するためです。参加者間のポイントツーポイント通信を回避するため、各参加者間の調整を必要とせずに、フロー内にさらに中間ステップを追加することもできます。このようなSagaフローの実装に飛び込む前に、Sagaが提供するトランザクションセマンティクスについていくらか時間をかけて考える価値があります。このパターンにより、すべてのサービスがローカルトランザクションを適用するか、障害が発生した場合に、すでに実行されているすべてのローカルトランザクションが補正され、データの変更が効果的に適用されなくなります。Sagaを構成するすべてのトランザクションが正常に実行され、システム全体が1つの一貫した状態から別の状態に移行後に、すべてのローカル制約が満たされることが保証されます。Sagaの実行中にローカルトランザクションがコミットされるため、Sagaが最終的に失敗し、以前に適用されたすべてのトランザクションが補正される可能性があるにもかかわらず、それらの変更は他の並行トランザクションですでに表示可能です。uncommitted)」と同等です。Sagaのローカルトランザクションがコミットされると、それらの変更は恒久的に永続化されます。サービスの障害が発生したり再起動した後など。(たとえば、注文サービスで注文書を出すユーザ)、システムには結果整合性があります。さまざまな参加サービスのロジックに従って、注文書が正しい状態になるまでに時間がかかります。非同期的に発生する可能性があります。可能な場合は常にサービス間に非同期通信を優先すべきです。これは、送信サービスを消費サービスの可用性から解くためです。次のセクションで説明するように、変更データキャプチャのおかげで、Kafka自体の可用性さえも問題になりません。上記のように、Sagaコーディネーターは、リクエストおよび応答メッセージチャネルを介して、参加しているサービスと非同期的に通信することが望ましいです。Kafkaは、これらのチャネルを実装するための非常に人気のある選択肢です。Sagaフロー全体の一部を実行するために、特定のデータベースにトランザクションを適用する必要もあります。データベーストランザクションを実行し、その直後に対応するメッセージをKafkaに送信したくなるかもしれませんが、これは良い考えではありません。これらの2つのアクションは、データベースとKafkaにまたがり単一のトランザクションで発生しません。データベーストランザクションはコミットされても、Kafkaへの書き込みが失敗することがあり、一貫性のない状態になるのは時間の問題です。友だちは友だちへの二重書き込みを実行しません。テーブルにメッセージを挿入します。これは単一のデータベーストランザクション内で行われるため、サービスのモデルへの変更が保持され、メッセージがOutboxテーブルに安全に保存されるか、これらの変更が適用されないかのいずれかになります。Kafkaに送信できます。(at-least-once)」のセマンティクスを使用して行われます。特定の状況では、同じOutboxメッセージがKafkaに複数回送信される可能性があります。コンシューマが重複したメッセージを検出して無視できるようにするには、各メッセージに一意のIDを付けなければなりません。これは、たとえば、Kafkaメッセージヘッダとして伝播される、各メッセージプロデューサ固有のUUIDや単調に増加するシーケンスで可能です。Outboxパターンを使用したSagaの実装ツールボックスのOutboxパターンを使用すると、考えが少し明確になります。注文プレースメントへの着信後にフロー全体をトリガし、永続化した注文モデルとSaga実行ログを網羅してローカル状態を更新することにより、他の2つの参加サービスに次々にメッセージを送信します。これら2つのサービスは、Kafkaを介して受信したメッセージに反応し、データ状態を更新するローカルトランザクションを実行し、Outboxテーブルを介してコーディネーターに応答メッセージを送信します。Outboxパターンを使用したSagaオーケストレーションこのアーキテクチャの完全な概念実証の実装は、GitHubのDebeziumのサンプルリポジトリにあります。Connect上で実行され、3つの異なるデータベースの変更をサブスクライブし、DebeziumのOutboxイベントルーティングコンポーネントを使用して、対応するKafkaトピックに送信します。ネイティブバイナリにコンパイルされるクラウドネイティブマイクロサービスを構築するためのスタックであるQuarkusを使用して実装されます。Kafkaからのメッセージを消費してデータベースに書き込む手段が提供される限り、他のスタックや言語を使用してパターンを実装することもできます。異なる実装技術を組み合わせることも可能です。関係する4つのKafkaトピックがあります。クレジット承認メッセージのリクエストとレスポンスのトピック、および支払いメッセージのリクエストとレスポンスのトピックです。Sagaの実行が成功した場合、正確に4つのメッセージが交換されます。ステップの1つが失敗し、補償トランザクションが必要な場合、補償される各ステップのリクエストとレスポンスメッセージの追加のペアがあります。順序保証スケーリングの目的で、Kafkaトピックを複数のパーティションに編成できます。パーティション内でのみ、コンシューマがプロデューサによって送信されたのとまったく同じ順序でメッセージを受信することが保証されます。デフォルトでは、同じキーを持つすべてのメッセージは同じパーティションに入れられます。Sagaの一意のIDは、Kafkaメッセージキーの自然な選択です。これにより、1つのSagaインスタンスのメッセージの正しい処理順序が保証されます。複数のSagaインスタンスは、Sagaメッセージ交換に使用されるトピックが異なるパーティションに配置される場合、並行して処理できます。成功時のSagaフローの実行シーケンス各サービスは、独自のデータベースのOutboxテーブルを介して送信メッセージを送信します。そこから、メッセージはDebeziumを介してキャプチャされ、Kafkaに送信され、最終的に受信サービスによって消費されます。メッセージを送受信すると、オーケストレーターとして動作する注文サービスは、Sagaの進行状況をローカルの状態テーブルに保持します。すべての参加者は、消費したメッセージのIDをジャーナルテーブルに記録して、後で重複した場合に特定します。顧客のクレジットカードの有効期限が切れているために支払いのステップが失敗したとしましょう。その場合、顧客サービスで以前に予約した与信額を再度解放する必要があります。そのために、注文サービスは顧客サービスに補償リクエストを送信します。補償でのSagaフローの実行シーケンスサービス間のメッセージフローについて説明したので、次に注文サービスの実装の詳細について詳しく見ていきましょう。概念実証の実装は、単純なステートマシンの形式で汎用のSagaオーケストレーターを提供し、注文固有のSaga実装を提供します。これについては、以下でさらに詳しく説明します。テーブルのスキーマこのテーブルは、Sagaログの役割を果たします。特定のSagaインスタンスに関連付けられた任意のデータ構造。対応する注文書のIDや、Sagaのライフサイクル中に役立つその他の情報が含まれます。他の形式を使用することも考えられます。個々のステップのステータスを説明する文字列化されたJSON構造。Sagaの名目上の型、例えば「注文プレイスメント」。(この場合、失敗した更新をトリガするメッセージを再試行して、Sagaログから現在の状態を再ロードする必要があります)注文サービスが顧客と支払いサービスにリクエストを送信し、Kafkaから返信を受け取ると、Sagaの状態がこのテーブルを更新します。テーブルを追跡するためのDebeziumコネクタを設定することで、KafkaでのSagaの実行の進行状況をうまく調べることができます。支払いが失敗した注文書の状態遷移は次のとおりです。(credit-approval)」リクエストメッセージはOutboxテーブルにも保持されています。これがKafkaに送信されると、顧客サービスはそれを処理して返信メッセージを送信します。2}ここでも、メッセージはOutboxテーブルを介して送信されます。これが「支払い」リクエストです。これは失敗し、支払いシステムはこの事実を示す応答メッセージで応答します。(credit-approval)」ステップが顧客システムを介して補償される必要があることを意味します。4}サンプルのREADMEファイルの手順に従って、これを自分自信で試すことができます。ここには、注文の作成の成功と失敗のリクエストがあります。さまざまなサービスのOutboxテーブルから供給されたKafkaトピックで交換されたメッセージを調べるための手順もあります。それでは、ユースケース固有の実装のいくつかの部分を見てみましょう。実装から最初のOutboxイベントを取得して、Outboxテーブルに永続化します。クラスは、Sagaフローのすべてのユースケース固有の部分を実装します。「支払い」応答メッセージのイベントハンドラ。CreditStatus.CANCELLED));...顧客と支払いサービスの実装は根本的に新しいものではないため、簡潔にするためにここでは省略します。こことここで完全なソースコードを見つけることができます。整合性が達成されるようにすることです。ここでは失敗のシナリオではないことに注意してください。参加者がフロー全体の一部を正常に実行できず、その結果、適切な補償ローカルトランザクションが実行されることが明示的に予想されます。これはまた、そのような一般的に予想される実行の失敗がローカルデータベーストランザクションのロールバックを引き起こしてはならないことを意味します。しないと、応答メッセージがOutboxを介してオーケストレーターに返送されません。それを念頭に置いて、考えられるいくつかの障害シナリオについて説明しましょう:Kafkaメッセージのイベントハンドラが例外を発生するローカルデータベーストランザクションがロールバックされ、メッセージコンシューマは、メッセージを処理できたことをKafkaブローカに確認しません。ブローカはメッセージが処理されたという確認を受け取らないため、しばらくすると、確認の応答がされるまでメッセージを繰り返し再送信します。メッセージが処理されるまでSagaフローは続行できないため、このような状況を検出するには、監視が行われなければなりません。Debeziumコネクタが、OutboxメッセージをKafkaに送信した後、ソースデータベースのトランザクションログでオフセットをコミットする前にクラッシュするコネクタを再起動した後、最後にコミットされたログオフセットから開始して、Outboxテーブルからメッセージを読み取り続けます。その結果、一部のOutboxイベントが2回送信される可能性があります。そのため、一意のメッセージIDを使用する例で実装されているように、すべての参加者がべき等である必要があり、コンシューマはジャーナルテーブルを介して正常に処理されたメッセージを追跡します。ネットワークの分割などが原因で、Kafkaブローカが実行されていないか、到達できないDebeziumコネクタは、Kafkaが利用可能になり、再びアクセス可能になった後、作業を再開できます。それまで、Safaフローは自然に進むことはできません。メッセージは処理されるが、Kafkaでの確認が失敗するメッセージは再びコンシューマサービスに渡されます。コンシューマサービスはジャーナルテーブルでメッセージのIDを見つけ、重複したメッセージを無視します。複数のSagaステップを並行して処理する場合のSaga状態テーブルの同時更新オーケストレーターが参加サービスを次々にトリガするシーケンシャルフローについて説明しましたが、複数のステップを並行して処理するSagaの実装を想像することもできます。この場合、同時に到着する応答メッセージは、Saga状態テーブルを更新するために競合する可能性があります。この状況は、そのテーブルに実装された楽観的ロックによって検出され、Saga状態の置き換えられたバージョンに基づいて更新をコミットしようとするイベントハンドラが失敗し、ロールバックして、再試行します。保証が付いた結果整合性のあるシステムのセマンティクスです。分散トレース分散システム間のイベントフローを設計する場合、すべてが正しく効率的に実行されるようにするために、運用上のインサイトが不可欠です。分散トレースは、そのようなインサイトを提供します。それはそのような相互作用に貢献する個々のシステムからトレース情報を収集し、呼び出しフローの調査を可能にします。UIは非常に貴重なツールになります。(OpenTelemetryサポートはロードマップにあります)。いサービスからトレース情報を収集し、エンドツーエンドのトレースを表示するように構成するだけで済みます。戻る方法をうまく示しています。1つのイベントハンドラがSagaの流れの役割を果たすのに不当に時間がかかる場合などのパフォーマンスのボトルネックを簡単に識別できます。まとめと展望Sagaパターンは長期にわたる「ビジネストランザクション」を実装するための強力で柔軟なソリューションを提供します。Kafkaで実装されたOutboxパターンのおかげで、Sagaコーディネーターは他の参加サービスの可用性から切り離されています。単一の参加者の一時的な停止は、Sagaフロー全体に影響を与えません。コンポーネントが再び復旧すると、Sagaは以前に中断されたポイントから続行されます。リモートサービスとのやり取りの必要性を可能な限り減らすサービスの削減を目指す必要があります。サンプルの与信限度額ロジックを注文サービスに移動して、顧客サービスとの調整を回避する選択肢があります。ビジネス要件によっては複数のサービスにまたがるこのような相互作用の必要性を回避できない場合があります。レガシーシステムや自身の管理下にないシステムを統合する場合です。Sagaのような複雑なパターンを実装する場合、それらの制約とセマンティクスを正確に理解することが重要です。提案されたソリューションのコンテキストで注意すべき2つのことは、固有の結果整合性と、包括的なビジネストランザクションの制限された分離レベルです。顧客の与信限度額の一部を割り当てると、最初の注文が最終的に処理されない場合でも、同時に送信されたその顧客からの別の注文が拒否される可能性があります。この記事で説明するサンプルプロジェクトは、CDCとOutboxパターンに基づいたSagaオーケストレーションのPoCレベルの実装を提供します。Quarkus拡張機能を使用して、前の部分を再利用可能なコンポーネントに抽出する可能性があります。これに興味がある場合は、Debeziumのメーリングリストに連絡してお知らせください。追加する可能性のある機能の1つは、複数のSagaステップを同時に実行する手段です。それが合理的かどうかはビジネス上の決定ですが、それをサポートすることは技術的な観点からは難しいことではありません。この場合、Saga状態の更新中の競合が重大な問題になる可能性があります。次のSagaの散乱収集を最適化では、これに対する潜在的な解決策について説明しています。経っても完了していないSagaを監視および識別するための機能があることも興味深いでしょう。提案された実装は、複数のサービスにまたがる「オールオアナッシング」セマンティクスでビジネストランザクションを確実に実行する手段を提供します。条件付きロジックを使用したフローなど、より複雑な要件を持つユースケースの場合は、既存のワークフローエンジンや、Kogitoなどのビジネスプロセス自動化ツールを確認してください。MicroProfileコミュニティは、DebeziumのようなトランザクションOutboxの実装との統合についても話し合っています。ソフトウェアエンジニアであり、オープンソース愛好家です。ツールであるDebeziumプロジェクトを率いています。スペックリーダであり、Layrry、Deptective、MapStructなどの複数のオープンソースプロジェクトを設立しています。EEプロジェクトに携わっていました。彼はドイツのHamburgを拠点としています。毎週火曜日に前週のまとめコンテンツをお送りいたします。(日本語版は不定期リリース)25万人のシニアな開発者コミュニティーにぜひご参加ください。サンプルを見るあなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。毎週火曜日に前週のまとめコンテンツをお送りいたします。(日本語版は不定期リリース)25万人のシニアな開発者コミュニティーにぜひご参加ください。サンプルを見る様々なイノベーターとアーリーアダプターがお送りするテクノロジーの概要を見る。自分がまだ知らないことに気づいていないと知るあなたが興味のあるトピックスをいつでも最新な情報に。あなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。Inc.プライバシーBT。