web-dev-qa-db-ja.com

多くのマイクロサービス間で共有モデルを管理するにはどうすればよいですか?

私の質問は this one に似ていますが、1つのケースに少し具体的です。

paymentsモデルがあり、これがmyreporting serviceとmy会計サービス

これら2つのサービスが、モデルへの相互依存関係によって結合されることは避けられないのでしょうか。

4
George Grainger

Ewanが述べたように、2つのサービスは、(厳密にオブジェクト指向の観点から)モデルではなく、交換されるデータによって結合されます。注:リンクをクリックすると404が表示されます。これはプライベートプロジェクトのようです。

Webサービスの観点から、データは既知のスキーマで交換されます。 XMLやJSONの場合もありますが、データの構造やその中のコンテンツほど重要ではありません。これにより、異機種混合のデプロイメント環境が可能になります。

サービス自体は、オブジェクトモデルなしで Go で定義できます。ビルトインのクライアントで出力を引き続き使用できます Python これは、出力をオブジェクトモデルにバインドします。

Webサービス環境でクライアントとサーバー間でモデルオブジェクトを共有することは、開発者にとって便利なことです。特にサードパーティのAPIを使用している場合は、常にそのオプションがあるとは限りません。


特定の例では、レポートサービスとアカウンティングサービスがpaymentsの同じスキーマを共有しているという事実は、必ずしもそれらを結合しているわけではありません。多くの場合、コアスキーマがあり、特定の目的のための拡張機能があります。主な統合はコアスキーマで行われます。

レポートサービスには、基本paymentsスキーマに加えて、レポートサービスにのみ関連するフィールドを含めることができます。会計サービスについても同様です。ただし、コアpaymentsスキーマが順守されている限り、そのサービスで使用されていない追加のフィールドは無視されます。

1
Berin Loritsch

結合がデータインターフェイスレベルにある限り、他の答えは正しいです。しかし、彼らはタイトルで提起された質問に実際には答えません:

多くのマイクロサービス間で共有モデルを管理するにはどうすればよいですか?

従来のマイクロサービスの知恵はエラーを緩く結合することです。できるだけ少ないコードを共有してください

直接コードを共有する際の問題の概要は、 here にあります。この抜粋は、いくつかの良い点に当てはまります(強調は私のものです):

デビッドは、すべてのコード共有が共有コードを介してサービスを接続することを強調しています。 DRY原則単一のサービス内に準拠して、単一の信頼できる情報源を作成すると、内部結合が作成されますが、単一の責任を持つサービスでは問題は発生しません。対照的に、境界をまたぐ場合、同じように見えるものもありますが、それらは異なるコンテキストにあり、異なるコードで実装され、異なるデータストアを使用する必要があります。Davidは、どのように見えても、接続に抵抗する必要があることを強くお勧めします。それらは、我々が境界を越えて異なるコンテキストを越えて結合するであり、泥の大きなボールへの直接パスであることを意味するためです。

この ebook は、マイクロサービス間でコードを共有することが一般的に悪い理由ですが、それが必要な悪であるというレンズを通して時々説明します。サービス間でコードを慎重に共有するのが実際的である場合があります。マイクロサービス間でコードを共有する方法/タイミングをよりよく理解するには、「共有するように教えられた」AntiPatternセクションをすべて読むことをお勧めします。後世のために、適切な場合にコードを共有するために説明する4つのアプローチを次に示します。

  1. 共有プロジェクト:共有プロジェクトを使用すると、共有プロジェクトにある共通のソースコードと各サービスプロジェクトの間のコンパイル時バインディングが形成されます。これにより、ソフトウェアの変更と開発が容易になりますが、実行時に潜在的な問題や驚きを引き起こし、アプリケーションの堅牢性を低下させるため、私のお気に入りの共有手法ではありません。共有プロジェクトの手法の主な問題は、通信と制御です。どの共有モジュールが変更されたのか、またその理由を知ることは困難であり、特定の変更が必要かどうかを制御することも困難です。誰かが共有モジュールに重大な変更を加えたことを発見するためだけにマイクロサービスをリリースする準備ができており、デプロイ前にコードを変更して再テストする必要があると想像してください。

  2. 共有ライブラリ:コードを共有する必要がある場合のより良いアプローチは、共有ライブラリ(.NETアセンブリやJARファイルなど)を使用することです。共有ライブラリ内のモジュールに加えられた変更ごとに、開発者は最初にライブラリを作成し、次にサービスを再起動してから再テストする必要があるため、このアプローチでは開発がさらに困難になります。ただし、共有ライブラリー手法の利点は、ライブラリーをバージョン管理できるため、サービスのデプロイメントとランタイムの動作をより適切に制御できることです。共有ライブラリに変更が加えられ、バージョン管理されている場合、サービス所有者はその変更をいつ組み込むかを決定できます。

  3. 複製されたコード:マイクロサービスアーキテクチャで一般的な3番目の手法は、Don't-repeat-yourself(DRY)の原則に違反し、特定の機能を必要とするすべてのサービス間で共有モジュールを複製することです。レプリケーション手法は危険に思えるかもしれませんが、依存関係の共有を回避し、サービスの制限付きコンテキストを保持します。特に欠陥のために、複製されたモジュールを変更する必要がある場合、この手法で問題が発生します。この場合、すべてのサービスを変更する必要があります。したがって、この手法は、変更がほとんどないかまったくない、非常に安定した共有モジュールに対してのみ有効です。

  4. サービスの統合:サービス統合を使用することも可能な4番目のテクニックです。 2つまたは3つのサービスがすべていくつかの共通コードを共有していて、それらの共通モジュールが頻繁に変更されるとしましょう。いずれにしても、共通モジュールを変更してすべてのサービスをテストおよびデプロイする必要があるため、機能を1つのサービスに統合して、依存ライブラリを削除することもできます。

また、関連: https://softwareengineering.stackexchange.com/a/366237/209046


事例として、私は以前に#2と#3の両方を異なるプロジェクトで実行しました。 「マイクロサービス共通」ライブラリ(上記の電子書籍ではアンチパターンとして明示的に識別されています)でコードを共有し、モデルをあるサービスから別のサービスにコピー/貼り付け(実際には「マイクロサービス」ではありませんでした)して、個別に保守します。 #3の最も明らかな利点は、各サービスのフレームワークのアップグレードを個別に実行できることです。ただし、モデルコードを2か所で維持する必要があるという欠点があります(2つのサービスだけではそれほど苦痛ではありませんでした)。 #2については、「マイクロサービスの共通」パッケージの管理が、このプロジェクトの開発で最も苦痛な部分だったことをはっきりと覚えています。

4
Kyle McVay

それらはモデルによって結合されていません。

これらは、交換するデータの形式によって結合され、モデルに逆シリアル化されます。

彼らが話さなければならない場合、彼らはお互いを理解する必要があります。はい、それは事実上避けられないことです。理論的には、さまざまな構造を解釈できるAIを記述できるかもしれませんが、単に形式を交換するよりも簡単だとは思いません。

1
Ewan

Avroで定義されたスキーマを格納する(git)リポジトリを作成することをお勧めします。このように、スキーマ/契約は明確に定義されており、開発者は契約の言語固有の表現を導出できます。

https://avro.Apache.org/

0
Ron Klein