web-dev-qa-db-ja.com

マイクロサービス間でDTOを共有する方法は?

私のシナリオは次のとおりです。

さまざまな種類のセンサーからデータを受け取り、変換して永続化して、後でさまざまなフロントエンドサービスや分析サービスで使用できるように設計されたシステムを設計しています。

すべてのサービスをできる限り独立させるように設計しようとしていますが、問題があります。チームは、使用するDTOを決定しました。外向きのサービス(センサーデータの受信者)は独自の方法でデータを受信し、それをJSONオブジェクト(DTO)に変換して、メッセージブローカーに送信します。メッセージのコンシューマーは、センサーデータメッセージを読み取る方法を正確に知ることができます。

問題は、いくつかの異なるサービスで同じDTOを使用していることです。更新は複数の場所に実装する必要があります。明らかに、ここでは、DTOのいくつかの余分なフィールドまたは欠落しているフィールドがここにあり、サービスが更新されるまでほとんど問題はないように設計しましたが、それでも私はバグを抱えており、間違える。それは簡単に頭痛に変わるかもしれません。

私はシステムを間違って設計するつもりですか?そうでない場合、これを回避する方法は何ですか?または少なくとも私の心配を和らげるには?

33

私のアドバイス? これらのDTOは、あらゆる種類のライブラリのアプリケーション間で共有しないでください。または、少なくとも今はこれを行わないでください。

私は知っている、非常に直感に反するようです。コードを複製していますよね?ただし、これはビジネスルールではないため、より柔軟に対応できます。

DTOを送信するサービスは、Rest APIのように、メッセージコントラクトで厳密である必要があります。サービスは、DTOからの情報をすでに消費している他のサービスを壊すような方法でDTOを変更することはできません。

DTOを実行して新しいフィールドを追加すると、このDTOを使用する他のサービスifのみが更新され、新しいフィールドが必要になります。それ以外の場合は、忘れてください。 JSONをコンテンツタイプとして使用すると、DTOの実際のバージョンにこれらの新しいフィールドをマップしないサービスのコードを壊すことなく、新しい属性を作成して送信する柔軟性があります。

しかし、この状況が本当にあなたを悩ませているなら、あなたは Rule of Three に従うことができます:

再利用には2つの「ルール3」があります。(a)再利用可能なコンポーネントを構築するのは、使い捨てコンポーネントの3倍の困難です。(b)再利用可能なコンポーネントは、3つの異なるアプリケーションで十分に一般的なものになる前に試してみる必要があります。再利用ライブラリに受け入れます。

したがって、このDTOをサービス間で共有する前に、もう少し待ってみてください。

40
Dherik

マイクロサービスに関しては、サービスの 開発ライフサイクル も独立している必要があります。*

異なるSLDCと異なる開発チーム

実際のMSシステムでは、エコシステムの開発に関与する複数のチームが存在し、それぞれが1つ以上のサービスを担当しています。次に、これらのチームは異なるオフィス、都市、国、計画に配置されている可能性があります...おそらく、彼らはお互いを知らないため、知識やコードの共有が(可能な場合)非常に困難になります。しかし、共有コードは一種の共有の推論も意味するため、これは非常に便利です。特定のチームにとって意味のあるものは何でも、別のチームのために作成する必要がないことを思い出してください。たとえば、DTOが顧客の場合、顧客の解釈(または表示)は各サービスによって異なるため、実際のサービスによって異なる場合があります。

異なるニーズ、異なるテクノロジー

分離されたSLDCにより、チームはニーズに最も適したスタックを選択することもできます。特定のテクノロジーに実装されたDTOを課すと、チームの選択能力が制限されます。

DTOはビジネスルールでもサービス契約でもありません

DTOは実際には何ですか?データをある側から別の側に移動すること以外の目的がないプレーンオブジェクト。ゲッターとセッターのバッグ。まったく知識がないので、全体的に再利用する価値のある「知識」ではありません。それらのボラティリティはまた、それらを結合の悪い候補にします。

Dherikが述べたのとは逆に、他のサービスを同時に変更することなく、サービスがDTOを変更できることは必要です。サービスでなければなりません/ = /はトレラントリーダー、トレラントライターであり、フォールトトレラントです。それ以外の場合は、サービスアーキテクチャを意味のない方法で結合します。もう一度、そしてDherikの答えとは逆に、3つのサービスがまったく同じDTOを必要とする場合、サービスの分解中に問題が発生した可能性があります。

異なるビジネス、異なる解釈

サービス間に分野横断的な概念が存在する可能性があります(存在する可能性があります)が、すべてのサービスにそれらを同じ方法で解釈させるために標準モデルを課さなければならないという意味ではありません。

ケーススタディ

私たちの会社にはカスタマーサービスセールスおよびShippingの3つの部門があるとします。これらのそれぞれが1つ以上のサービスをリリースするとします。

顧客サービスは、そのドメイン言語により、顧客の概念を中心にサービスを実装します。ここで、顧客です。たとえば、お客様名前年齢性別メールとしてモデル化されます電話など.

ここで、販売配送は、それぞれのドメイン言語に従ってサービスをモデル化します。これらの言語では、概念customerも表示されますが、微妙な違いがあります。彼らにとって、顧客は(必然的に)ではありません。 セールスの場合、お客様は文書番号 a クレジットカードおよび請求先住所で、発送 a フルネーム配送先住所も。

SalesおよびShippingCustomer Serviceの正規データモデルを採用するように強制した場合、不必要な複雑さをもたらす可能性のある不要なデータを処理するように強制します。表現全体を維持し、顧客データを顧客サービスと同期させる必要がある場合。

関連リンク


* このアーキテクチャの強みはここにあります

12
Laiv

すべてのサービスをできるだけ独立したものにするように設計しています

eventsを公開する必要があります。イベントは、特定の時点で発生した何かについて確かな事実を表す特定のタイプのメッセージです。

各サービスには、明確に定義された責任があり、その責任に関連するイベントを公開する責任があります。

さらに、技術的なイベントではなく、ビジネス関連のイベントを表すイベントが必要です。例えば。 OrderCancelledイベントをOrderUpdatedよりもstatus: "CANCELLED"

そうすることで、キャンセルされた注文にサービスが対応する必要がある場合、そのイベントに関連するデータのみを運ぶ特定のタイプのメッセージをリッスンするだけで済みます。例えば。 OrderCancelledはおそらくorder_id。これに反応する必要のあるサービスは、注文について知る必要のあるものをすべて独自のデータストアに既に格納しています。

ただし、サービスがOrderUpdatedイベントしかリッスンしない場合、イベントのフローを解釈する必要があり、注文がキャンセルされたときに正しく完了するのは配送注文に依存していました。

ただし、あなたの場合、センサーデータを公開しているので、サービスを提供し、イベントをリッスンし、「ビジネスイベント」の新しいストリームを公開することは理にかなっています。 TemperatureThresholdExceededTemperatureStabilised

また、作成するマイクロサービスが多すぎることに注意してください。マイクロサービスは複雑さをカプセル化する優れた方法ですが、適切なサービス境界を見つけられない場合、複雑さはサービス統合にあります。そしてそれは維持するのが悪夢です。

サービスが多すぎたり小さすぎたりするよりも、サービスが少なすぎたり大きすぎたりする方がよいでしょう。

8
Pete