1. 概要

マイクロサービスは、近年人気が高まっています。 マイクロサービスの本質的な特徴の1つは、モジュール式で、分離されており、拡張が容易なことです。 マイクロサービスは連携してデータを交換する必要があります。これを実現するために、DTOと呼ばれる共有データ転送オブジェクトを作成します。

この記事では、マイクロサービス間でDTOを共有する方法を紹介します。

2. ドメインオブジェクトをDTOとして公開する

アプリケーションドメインを表すモデルは、マイクロサービスを使用して管理されます。 ドメインモデルはさまざまな懸念事項であり、DAOレイヤーのデータモデルから分離します。

これの主な理由は、サービスを通じてクライアントにドメインの複雑さを公開したくないということです。 代わりに、公開します RESTAPIを介してアプリケーションクライアントにサービスを提供するサービス間のDTO。 DTOはこれらのサービス間を通過しますが、ドメインオブジェクトに変換します

上記のサービス指向アーキテクチャは、ドメインオブジェクトへのDTOのコンポーネントとフローを概略的に示しています。

3. マイクロサービス間のDTO共有

例として、顧客が製品を注文するプロセスを取り上げます。 このプロセスは、Customer-Orderモデルに基づいています。 サービスアーキテクチャの側面からプロセスを見てみましょう。

カスタマーサービスがリクエストデータをオーダーサービスに次のように送信するとします。

"order": {
    "customerId": 1,
    "itemId": "A152"
}

顧客サービスと注文サービスは、 契約それ以外の場合はサービスリクエストであるコントラクトは、JSON形式で表示されます。 Javaモデルとして、 OrderDTO クラスは、カスタマーサービスとオーダーサービス間のコントラクトを表します。

public class OrderDTO {
    private int customerId;
    private String itemId;

    // constructor, getters, setters
}

3.1. クライアントモジュール(ライブラリ)を使用したDTOの共有

マイクロサービスは、リクエストを処理するために他のサービスからの特定の情報を必要とします。 注文支払い要求を受け取る3番目のマイクロサービスがあるとしましょう。 注文サービスとは異なり、このサービスにはさまざまな顧客情報が必要です。

public class CustomerDTO {
    private String firstName;
    private String lastName;
    private String cardNumber;

    // constructor, getters, setters
}

配送サービスも追加すると、顧客情報は次のようになります。

public class CustomerDTO {
    private String firstName;
    private String lastName;
    private String homeAddress;
    private String contactNumber;

    // constructor, getters, setters
}

そのため、 CustomerDTO クラスを共有モジュールに配置しても、意図した目的は果たされなくなります。 これを解決するために、別の方法にアプローチします。

各マイクロサービスモジュール内に、クライアントモジュール(ライブラリ) を作成し、その隣にサーバーモジュールを作成しましょう。

order-service
|__ order-client
|__ order-server

order-client モジュールには、カスタマーサービスと共有されるDTOが含まれています。 したがって、order-clientモジュールの構造は次のとおりです。

order-service
└──order-client
     OrderClient.java
     OrderClientImpl.java
     OrderDTO.java

OrderClient は、注文要求を処理するためのorderメソッドを定義するインターフェースです。

public interface OrderClient {
    OrderResponse order(OrderDTO orderDTO);
}

order メソッドを実装するには、 RestTemplate オブジェクトを使用して、POST要求をOrderサービスに送信します。

String serviceUrl = "http://localhost:8002/order-service";
OrderResponse orderResponse = restTemplate.postForObject(serviceUrl + "/create", 
  request, OrderResponse.class);

さらに、order-clientモジュールを使用する準備が整いました。 これで、customer-serviceモジュールの依存ライブラリになります。

[INFO] --- maven-dependency-plugin:3.1.2:list (default-cli) @ customer-service ---
[INFO] The following files have been resolved:
[INFO]    com.baeldung.orderservice:order-client:jar:1.0-SNAPSHOT:compile

もちろん、これには、 order-server モジュールがなければ、「/create」サービスエンドポイントを注文クライアントに公開する目的はありません。

@PostMapping("/create")
public OrderResponse createOrder(@RequestBody OrderDTO request)

このサービスエンドポイントのおかげで、カスタマーサービスは注文クライアントを介して注文リクエストを送信できます。 クライアントモジュールを使用することにより、マイクロサービスはより分離された方法で相互に通信します。 DTOの属性は、クライアントモジュール内で更新されます。 したがって、契約の解除は、同じクライアントモジュールを使用するサービスに限定されます。

4. 結論

この記事では、マイクロサービス間でDTOオブジェクトを共有する方法について説明しました。 せいぜい、マイクロサービスクライアントモジュール(ライブラリ)の一部として特別な契約を結ぶことでこれを達成します。 このようにして、APIリソースを含むサーバー部分からサービスクライアントを分離します。 その結果、いくつかの利点があります

  • サービス間のDTOコードに冗長性はありません
  • 契約違反は、同じクライアントライブラリを使用するサービスに限定されます

Spring Bootアプリケーションのコードサンプルは、GitHubから入手できます。