9 LRAでのアプリケーションの開発

Node.jsのマイクロサービス対応トランザクション・マネージャ(MicroTx)ライブラリは、新しいLRAトランザクションを開始したり、既存のLRAトランザクションに参加したりする機能を提供します。

開始する前に、MicroTxをインストールし、アクセスできることを確認してください。

マイクロサービスの開発、テストおよびデプロイを個別に行います。MicroTxを使用してアプリケーションのトランザクションを管理するには、既存のアプリケーション・コードにいくつか変更を加えて、MicroTxライブラリによって提供される機能を統合する必要があります。

MicroTxを使用してLRAトランザクションを管理するアプリケーションを開発するには、次のワークフローをガイドとして使用します。

タスク 説明 詳細
MicroTxライブラリ・プロパティの構成情報を指定します。 Node.jsアプリケーションがライブラリにアクセスできるように、すべてのトランザクション参加側およびトランザクション・イニシエータのNode.jsアプリケーションに対してこのステップを実行します。 ライブラリ・プロパティの構成
MicroTxライブラリをアプリケーション・コードと統合します。 次の要因に基づいて、ライブラリを統合する適切な手順を選択します:
  • アプリケーションの開発フレームワーク
  • アプリケーションがトランザクションを開始するか、トランザクションに参加するか
ライブラリは、JavaおよびNode.jsのアプリケーションで使用できます。次のタスクのいずれかを実行します。
セッション・アフィニティの有効化 内部メモリーをデータ・ストアとして使用し、トランザクション・コーディネータを複数のレプリカにデプロイする場合は、LRAおよびXAトランザクションに対してセッション・アフィニティを有効にする必要があります。TCCトランザクションに対してセッション・アフィニティを有効にする必要はありません。 セッション・アフィニティの有効化
アプリケーションのデプロイ アプリケーションでライブラリ・ファイルを使用してから、アプリケーションをインストールします。 アプリケーションのデプロイ

9.1 LRAでのJavaアプリケーションの開発

Eclipse MicroProfileによって、JavaアプリケーションのLRA仕様が提供されます。

詳細は、https://download.eclipse.org/microprofile/microprofile-lra-1.0-M1/microprofile-lra-spec.htmlを参照してください。

Helidonによって、LRAクライアント仕様のための実装が提供されます。詳細は、https://helidon.io/docs/v2/#/mp/lra/01_introductionを参照してください。アプリケーションの実装の詳細は、https://danielkec.github.io/blog/helidon/lra/saga/2021/10/12/helidon-lra.htmlを参照してください。

アプリケーションのビジネス・ロジックがトランザクションを完了するために複数のAPIコールにまたがる場合

この項では、アプリケーションのビジネス・ロジックが複数のAPIコールにまたがってトランザクションを完了するときに、Oracle_Tmm_Tx_Tokenトークンがどのように伝播されるかを説明します。YAMLファイルでtransactionTokenEnabledtrueに設定し、アプリケーションのビジネス・ロジックがトランザクションを完了するために複数のAPIコールにまたがる場合、Oracle_Tmm_Tx_Tokenの値を取得し、ユーザーが行う後続のすべてのAPIコールのリクエスト・ヘッダーでそれを渡す必要があります。

アプリケーションのビジネス・ロジックがトランザクション全体を完了するためにユーザーによる1つのAPIコールしか必要ない場合、これらのステップはスキップしてください。アプリケーションのビジネス・ロジックでユーザーによる1つのAPIコールしか必要がないときにOracle_Tmm_Tx_Tokenトークンがどのように伝播されるかを理解するには、「Oracle_Tmm_Tx_Tokenトランザクション・トークンについて」を参照してください。

旅行予約アプリケーションについて考えてみますが、これにはユーザーによる2つのコールが必要です。最初のコールは、トランザクションを開始して、暫定的な予約を行います。アプリケーションでは、予約を確定または取り消すために、ユーザーによる2番目のAPIコールが必要です。このようなシナリオで、アプリケーションのビジネス・ロジックが1つのトランザクションを完了するためにユーザーによる複数のAPIコールにまたがるときは、ユーザーによる後続のAPIコールのリクエスト・ヘッダーにOracle_Tmm_Tx_Tokenを含めて、予約の確定または取消を行う必要があります。

次のステップでは、MicroTxOracle_Tmm_Tx_Tokenトランザクション・トークンを作成して最初のコールに伝播する方法と、ユーザーによる後続のAPIコールにOracle_Tmm_Tx_Tokenを含める方法について説明します。

  1. ユーザーがトランザクションを開始すると、トランザクション・イニシエータ・サービスがMicroTxにリクエストを送信します。
  2. MicroTxはトランザクション・イニシエータに応答し、レスポンス・ヘッダーでOracle_Tmm_Tx_Tokenを返します。

    MicroTxライブラリは、指定した秘密キーと公開キーのペアに基づいてこのトークンを作成します。ユーザーがOracle_Tmm_Tx_Tokenトランザクションを作成したり、リクエスト・ヘッダーで渡したりする必要はありません。

    MicroTxは、複数のヘッダーおよびトークンを使用して動作します。わかりやすくするために、この項ではOracle_Tmm_Tx_Tokenトランザクション・トークンについてのみ説明します。

  3. 参加側サービスからトランザクション・コーディネータへのコールを保護するため、MicroTxライブラリは、後続のすべてのコールのリクエスト・ヘッダーにOracle_Tmm_Tx_Tokenを渡します。
  4. MicroTxは、ユーザーからの最初のコールに応答する際に、レスポンス・ヘッダーでOracle_Tmm_Tx_Tokenを返します。レスポンス・ヘッダーからOracle_Tmm_Tx_Tokenの値を取得します。
  5. ユーザーが行う後続のすべてのAPIコールで、Oracle_Tmm_Tx_Tokenをリクエスト・ヘッダーに手動で含める必要があります。前のステップで取得した値を指定します。

こうすると確実にユーザーによる複数のAPIコールが結び付けられ、すべてのコールが1つのトランザクションの一部と見なされます。

9.2 ライブラリ・プロパティの構成

MicroTxライブラリ・プロパティの構成情報を指定します。このステップは、トランザクションに参加または開始するすべてのNode.jsアプリケーションに対して実行する必要があります。

任意のコード・エディタでtmm.propertiesファイルを開き、次のパラメータの値を入力してMicroTxライブラリを構成します。
  • oracle.tmm.TcsUrl: MicroTxアプリケーションにアクセスするためのURLを入力します。「MicroTxへのアクセス」を参照してください。この値はトランザクション・イニシエータ・アプリケーションの場合に入力する必要があります。トランザクション参加側アプリケーションの場合、この値を指定する必要はありません。

  • oracle.tmm.CallbackUrl: 参加側サービスのURLを入力します。MicroTxは、指定されたURLを使用して参加側サービスに接続します。この値を次の形式で指定します。
    https://externalHostnameOfApp:externalPortOfApp/
    説明
    • externalHostnameOfApp: イニシエータ・サービスまたは参加側サービスの外部ホスト名。たとえば、bookTicket-appです。
    • externalPortOfApp: 参加側サービスにリモートでアクセスできるポート番号。たとえば、8081です。
    トランザクション参加側アプリケーションには、この値を指定する必要があります。トランザクション・イニシエータ・アプリケーションでは、この値を指定する必要はありません。
  • oracle.tmm.PropagateTraceHeaders: トランザクションを全面的にトレースする場合は、これをtrueに設定します。これにより、すべての受信リクエストおよび送信リクエストのトレース・ヘッダーが伝播されます。Helidonベースのマイクロサービスの場合、Helidonフレームワークがデフォルトでトレース・ヘッダーを伝播するため、トレース・ヘッダーを2回伝播しないように、このプロパティをfalseに設定します。このプロパティをtrueに設定できるのは、Helidon構成でトレース・ヘッダーの伝播が無効になっているときに、MicroTxを使用して分散トレースを有効にする場合です。その他のマイクロサービスの場合は、このプロパティをtrueに設定します。

たとえば、
oracle.tmm.TcsUrl = http://tmm-app:9000/api/v1
oracle.tmm.CallbackUrl = https://bookTicket-app:8081
oracle.tmm.PropagateTraceHeaders = true

アプリケーションとMicroTxが同じKubernetesクラスタ内にある場合はHTTPプロトコルを使用し、それ以外の場合はHTTPSプロトコルを使用します。

これらの構成値を環境変数として指定することもできます。application.propertiesファイルと環境変数の両方に値を指定した場合、環境変数に設定されている値がプロパティ・ファイルの値をオーバーライドすることに注意してください。

次の例は、環境変数を構成するためのサンプル値を示しています。

export ORACLE_TMM_TCS_URL = http://tmm-app:9000/api/v1
export ORACLE_TMM_CALLBACK_URL = http://bookTicket-app:8081
export ORACLE_TMM_PROPAGATE_TRACE_HEADERS = true

環境変数名では大/小文字が区別されることに注意してください。

9.3 LRAでのNode.jsアプリケーションの開発

Node.jsのMicroTxライブラリは、新しいLRAトランザクションを開始したり、既存のLRAトランザクションに参加したりする機能を提供します。このライブラリをNode.jsアプリケーション・コードに統合する必要があります。

開始する前に、MicroTxライブラリのプロパティ値を構成していることを確認してください。

  1. Node.jsのMicroTxライブラリをpackage.jsonファイルに依存関係として追加します。ライブラリ・ファイルは、installation_directory/otmm-RELEASE/otmm/nodejsフォルダにあります。
    "dependencies": {
        "tmmlib-node": "file:tmmlib-node-RELEASE.tgz"
      }
  2. プロパティ値を定義したtmm.propertiesファイルを渡して、マイクロサービスのMicroTxライブラリ・プロパティを構成します。
    TrmConfig.init('./tmm.properties');
  3. MicroTxおよびExpressライブラリをインポートします。
    import { Request, Response, Router } from 'express';
    import { getLRAId, LRA, LRAConfig, LRAType, ParticipantStatus, cancelLRA, LRA_HTTP_CONTEXT_HEADER, LRA_HTTP_ENDED_CONTEXT_HEADER } from "tmmlib-node/lra/lra";
    import { getHeaderValue } from 'tmmlib-node/util/trmutils';
  4. プログラム内でリクエストを処理するルーター・オブジェクトを作成します。
    次のコードを使用して、flightSvcRouterという名前のルーター・オブジェクトを作成します。
    const flightSvcRouter = Router();
  5. MicroTx LRAコーディネータのURLを入力します。この属性値を取得するには、MicroTxへのアクセスに使用するURLに/lra-coordinatorを追加します。たとえば、https://tmm-app:9000/api/v1MicroTx URLの場合、lraCoordinatorUrlhttps://tmm-app:9000/api/v1/lra-coordinatorです。
    const lraCoordinateUrl = process.env.ORACLE_TMM_TCS_URL
  6. 次のコードを追加して、トランザクション・イニシエータ・サービスおよびトランザクション参加側サービスのRESTエンドポイントのLRAConfigオブジェクトを初期化します。サービスによって多数のREST APIエンドポイントが公開されることがありますが、LRAConfigオブジェクトを初期化する必要があるのは、LRAトランザクションに参加する必要があるREST APIエンドポイントのみです。
    const lra: LRA = new LRA("/flight", LRAType.REQUIRES_NEW);
    lra.end = false;
    lra.timeLimitInMilliSeconds = 100000;
    new LRAConfig(lraCoordinateUrl, flightSvcRouter, "/flightService/api", lra, "/complete", "/compensate", "/status", "/after", "", "", "");

    説明

    • /flightは、LRAトランザクションに参加するためにトランザクション・イニシエータ・アプリケーションが公開するREST APIエンドポイントです。
    • LRAType.REQUIRES_NEWは、サービスが既存のLRAトランザクションに参加するか、新しいトランザクションを作成するかを決定します。LRATypeREQUIRES_NEWに設定すると、新しいトランザクションが作成されます。LRATypeMANDATORYに設定すると、サービスが既存のトランザクションに参加します。LRAType値の詳細は、マイクロサービス対応トランザクション・マネージャTypeScript APIリファレンスを参照してください。
    • flightSvcRouterは、事前に作成しておいたルーター・オブジェクトです。
    • /flightService/apiは、flightSvcRouterルーターのマウント・ポイントです。これは、LRAConfigオブジェクトのapplRouterMountPathフィールドの値です。
    • timeLimitInMilliSecondsは、トランザクションを完了または補正する必要がある期間(ミリ秒)です。指定した期間内にトランザクションが完了しない場合、MicroTxはトランザクションを補正します。業務要件に基づいて期限を決めてください。
    • "/complete"、"/compensate"、"/status"、"/after"は、アプリケーションのビジネス・ロジックを定義するためのREST APIエンドポイントです。

    LRAトランザクション中に、MicroTxは、指定したREST APIエンドポイントからのすべての送信リクエストのリンク・ヘッダーを追加します。

  7. LRAConfigオブジェクトの作成時に指定したすべてのREST APIエンドポイントに対してビジネス・ロジックを定義します。
    flightSvcRouter.put('/complete', async (req, resp) => {
    //application business logic
    });
    
    flightSvcRouter.put('/compensate', async (req, resp) => {
    //application business logic
    });
    
    flightSvcRouter.put('/status', async (req, resp) => {
    //application business logic
    });
    
    flightSvcRouter.put('/after', (req, resp) => {
    //application business logic
    });

    ここで、flightSvcRouterは、事前に作成しておいたルーター・オブジェクトです。このサンプル・コードはputのみを示していますが、ビジネス・ロジックに基づいて任意のHTTP動詞を使用できます。

  8. 変更内容を保存します。