クラウドネイティブなマイクロサービスアーキテクチャの実践講座 第4節 マイクロサービスの分割とAPIインターフェースの設計

講義 08: サンプル アプリケーションをマイクロサービスに分割する方法

Lesson 07 でドメイン駆動設計の基本概念を紹介した後、このレッスンではドメイン駆動設計に関連するアイデアをマイクロサービスの分割に適用する方法を紹介します。

マイクロサービス部門

マイクロサービス アーキテクチャ アプリケーションの設計と実装において、最も重要なタスクを見つけたい場合、それは非マイクロサービスの分割に違いありません。マイクロサービス アーキテクチャの中核は、複数のマイクロサービスが連携して構成される分散システムであり、マイクロサービスの分割が完了して初めて、各マイクロサービスの責任が明確になり、マイクロサービス間の相互作用モードが決定され、次に進むことができる API 設計の各マイクロサービスは、各マイクロサービスの最終的な実装、テスト、および展開です。


上記のプロセスからわかるように、マイクロサービスの分割は、アプリケーションの設計と実装のチェーン全体の最初のリンクです。チェーン内の各リンクの変更は、後続のリンクに影響を与えます. マイクロサービス部門の最初のリンクとして、変更があれば後続のすべてのリンクに影響します. 最後に、マイクロサービスの実装中に一部の機能を他のマイクロサービスに移行する必要があることを認識してはなりません。これが発生した場合、関連するマイクロサービスの API と実装の両方を変更する必要があります。


もちろん、実際の開発において、マイクロサービスの分割を完全に変更することは現実的ではありません。マイクロサービス分割の段階で、分析に力を入れれば得られるメリットは非常に大きいです。

マイクロサービスと境界付けられたコンテキスト

第07回では、ドメイン駆動設計における定義済みコンテキストの概念を紹介しました.ドメイン駆動設計の考え方をマイクロサービスアーキテクチャに適用すると、マイクロサービスと定義済みコンテキストを1対1で対応させることができます. . 境界付けられた各コンテキストは、マイクロサービスに直接対応し、コンテキスト マッピングのパターンを使用して、マイクロサービス間の相互作用の方法を定義します。


このように、マイクロサービスの分割の問題は、ドメイン駆動設計で定義されたコンテキストの分割の問題に変換されます。ドメイン駆動設計について十分に理解している場合は有利ですが、そうでない場合は、レッスン 07 の内容からすぐに始めることができます。


具体的な説明の例として、このコラムのサンプル アプリケーションを取り上げてみましょう。

サンプル アプリケーションのマイクロサービス パーティショニング

レッスン 06 では、サンプル アプリケーションのユーザー シナリオを紹介します。これらのシナリオに基づいて、アプリケーションのドメインを決定できます。実際のアプリケーション開発では、通常、ドメインの専門家やビジネス担当者が参加する必要がありますが、ビジネス担当者とのコミュニケーションを通じて、ドメインをより明確に理解することができます。サンプル アプリケーションについては、アプリケーション ドメインが比較的生命に近いため、関連する導入を簡単にするために、ドメイン分析を自分で行います。ただし、これには欠点があります。つまり、開発者が行うドメイン分析は、必ずしも実際のビジネス プロセスを反映しているとは限りません。ただし、サンプル アプリケーションの場合は、これで十分です。


ドメイン駆動設計はドメインをコアとし、ドメインは問題空間ソリューション空間に分割されます。


問題領域は、ビジネス レベルで考えるのに役立ち、コア ドメインが依存するドメインの一部であり、コア ドメインと、必要に応じて他のサブドメインを含みます。コア ドメインは、開発するソフトウェア システムのコアであるため、ゼロから作成する必要があります。他のサブドメインが既に存在するか、ゼロから作成する必要がある場合があります。問題空間の中心的な問題は、サブフィールドをどのように識別して分割するかです。


ソリューション スペースは、 1 つ以上の境界付けられたコンテキストと、コンテキスト内のモデルで構成されます。理想的には、定義されたコンテキストとサブドメインの間に 1 対 1 の対応があります。このように、ビジネスレベルから分割を開始し、実装レベルで同じ分割方法を採用することで、問題空間とソリューション空間の完全な統合を実現できます。実際には、定義されたコンテキストとサブフィールドが 1 対 1 で対応することはほとんどありません。ソフトウェア システムの実装では、通常、既存のレガシー システムや外部システムと統合する必要があり、これらのシステムには独自の定義済みコンテキストがあります。実際には、複数の境界付きコンテキストが同じサブフィールドに属するか、1 つの境界付きコンテキストが複数のサブフィールドに対応する方が現実的です。


ドメイン駆動設計の考え方は、ドメインから始めてサブドメインを分割し、サブドメインから定義されたコンテキストとコンテキスト内のモデルを抽象化し、定義された各コンテキストがマイクロサービスに対応します。

コアエリア

コア ドメインは、ソフトウェア システムの価値が存在する場所であり、設計の出発点でもあります。ソフトウェアシステムを開始する前に、ソフトウェアシステムのコアバリューを明確に理解する必要があります.そうでない場合は、まずソフトウェアシステムのセールスポイントを検討する必要があります.異なるソフトウェアシステムには異なるコア領域があります. タクシー配車アプリケーションとして、そのコア領域は、乗客を迅速、快適、安全に移動させる方法であり、Didi Taxi や Uber などのタクシー配車アプリケーションのコア領域でもあります。ハッピートラベルアプリケーションを例にとると、このようなコアエリアは少し大きすぎます.ハッピートラベルアプリケーションは、コアエリアを単純化し、乗客を素早く移動させる方法のみに焦点を当てています.


コア ドメインに適切な名前を付ける必要があります。ハッピートラベルの核となる領域は、車を呼ぶ必要のある乗客と旅行サービスを提供するドライバーとをいかに迅速にマッチングさせるかということです。ユーザーが旅程を作成すると、システムは利用可能なドライバーにそれを配布します. ドライバーが旅程を受信すると、システムは旅程を配布するドライバーを選択します. コア領域は旅程のディスパッチに焦点を当てているため、旅程の配布という名前が付けられています。

フィールドの概念

次に、ドメイン内の概念を列挙します。これは、頭に浮かぶすべての関連する概念を 1 つずつリストするためにホワイトボードで実行できるブレインストーミング プロセスです. 概念は名詞です. 最も初期の概念は旅程です, これは、特定の出発点から終点への旅を意味します. 旅程から出発して, 乗客とドライバーの概念を導き出すことができます. 乗客は旅程の開始者であり, 運転手は旅程の完成者です. 各旅程には開始点と終了点があり, 対応する概念は住所・アドレス。ドライバーは個人の車両を使用して旅行を完了するため、車両は別の概念です。


コンセプトに基づいて他のサブフィールドを見つけ、旅行のコンセプトはコア フィールドに属します。ドライバーと乗客は、さまざまな独立したサブドメインに属し、別々に管理する必要があります。これにより、乗客管理ドライバー管理の 2 つのサブドメインができます。住所の概念は住所管理のサブフィールドに属し、車両の概念はドライバー管理のサブフィールドに属します。


ドメイン内の概念によってサブドメインを分割した後、次のステップは、ドメイン内の操作から新しいサブドメインを引き続き発見することです。ユーザー シナリオでは、旅程を検証する必要があることが言及されており、この操作には対応するサブフィールドitinerary validationがあります。旅行が完了した後、乗客は支払いを行う必要があり、この操作には対応するサブフィールド支払い管理があります。


次の図は、サンプル アプリケーションのサブ領域を示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/ea934cc89d6e401fa2135ff11e96532c.png#pic_center)

境界付けられたコンテキスト

コア ドメインと他のサブドメインを特定したら、次のステップは、問題空間からソリューション空間に移動することです。まず、サブドメインが区切られたコンテキストにマッピングされ、区切られたコンテキストはサブドメインと同じ名前になります。次に、区切られたコンテキストがモデル化され、モデリングの主なタスクは関連する概念を具体化することです。

旅程の配布

旅程ディスパッチ モデルの重要なエンティティは旅程であり、旅程が存在する集計のルートでもあります。トリップには、値オブジェクトの住所として表される開始場所と終了場所があります。旅程は乗客によって開始されるため、旅程エンティティは乗客への参照を持っている必要があります.システムが旅程を受け入れるドライバーを選択すると、旅程エンティティはドライバーへの参照を持ちます. ライフサイクル全体で、旅行はさまざまな状態になる可能性があり、旅行の状態を説明する属性とそれに対応する列挙型があります。


次の図は、モデル内のエンティティと値オブジェクトを示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/33e17c00a7af4eac9a41b18e353642ce.png#pic_center)

旅客管理

乗客管理モデルの重要なエンティティは乗客であり、乗客が存在する集合体のルートでもあります。乗客エンティティの属性には、名前、電子メール アドレス、連絡先番号などが含まれます。乗客エンティティには、保存された住所のリストが関連付けられており、住所はエンティティです。


次の図は、モデル内のエンティティを示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/388c09a4214e41c5b245b1591d431d9b.png#pic_center)

ドライバー管理

ドライバー管理モデルの重要なエンティティはドライバーであり、ドライバーが存在する集合体のルートでもあります。ドライバー エンティティの属性には、名前、電子メール アドレス、連絡先番号などが含まれます。ドライバー エンティティに加えて、集計には車両エンティティも含まれます。車両エンティティの属性には、メーカー、モデル、製造日、ライセンスが含まれます。プレートナンバー。


次の図は、モデル内のエンティティを示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/72690b537a0e4b88a26df8b38791f65e.png#pic_center)

アドレス管理

住所管理モデルの重要な実体は住所であり、省、市町村、自治区から村、街路まで階層化されています。階層的な住所に加えて、もう 1 つの重要な情報があります。それは、経度と緯度を含む地理的な位置座標です。

旅程の確認

旅程検証モデルには、特定のエンティティは含まれませんが、旅程を検証するサービスおよび関連するアルゴリズムの実装が含まれます。

支払い管理

支払い管理モデルの重要なエンティティは、旅程や支払いステータスへの参照などの情報を含む支払いレコードです。

境界付けられたコンテキスト間の相互作用

定義されたコンテキストのモデルでは、旅程配車モデルの旅程エンティティは、乗客管理モデルの集合「乗客」のルート エンティティと、ドライバー管理モデルの集合「ドライバー」のルート エンティティを参照する必要があります。 . レッスン 07 で、外部オブジェクトは集約のルート エンティティのみを参照できることを説明しました。参照する場合は、エンティティ自体ではなく、集約のルート エンティティの識別子を参照する必要があります。Passenger エンティティと Driver エンティティの識別子はどちらも文字列型であるため、Trip エンティティには、それぞれ Passenger エンティティと Driver エンティティを参照する String 型の 2 つのプロパティが含まれています。


異なる区切りコンテキストのモデルに同じ概念が現れる場合、マッピングが必要であり、レッスン 07 で説明したコンテキスト マッピング モードをマッピングに使用できます。


住所管理と旅程ディスパッチの両方のコンテキストで、住所の概念があります。住所管理の住所エンティティは、さまざまなレベルの地理的名前を含む複雑な構造であり、マルチレベルの住所選択と住所クエリを実現します。旅程ディスパッチのコンテキストでは、住所は単に氏名と地理的な位置座標で構成されます。2 つのコンテキスト間をマッピングするために、モデル変換用の出張発送コンテキストに腐食防止レイヤーを追加できます。

既存のモノリシック アプリケーションの移行

このコラムのサンプル アプリケーションはゼロから作成した新しいアプリケーションであるため、マイクロサービスを分割する際に参照する既存の実装はありません。既存のモノリシック アプリケーションをマイクロサービス アーキテクチャに移行すると、マイクロサービスの分割がより追跡可能になります.モノリシック アプリケーションの既存の実装から、システムの各部分の実際の相互作用について学ぶことができ、より理解するのに役立ちます.責任に応じてそれらを分割するのは良いことです。このように分割されたマイクロサービスは、より実際の運用状況に近くなっています。


ThoughtWorks の Sam Newman は、彼の著書「Building Microservices」で製品 SnapCI のマイクロサービス部門での経験を共有しました. オープン ソース プロジェクト GoCD の関連する経験により、SnapCI チームは SnapCI のマイクロサービスを迅速に分割しました. ただし, GoCD と SnapCI のユーザー シナリオにはいくつかの違いがあります. しばらくして, SnapCI チームは、現在のマイクロサービス部門が多くの問題を引き起こしていることを発見しました. 多くの場合、複数のマイクロサービスにわたっていくつかの変更を加える必要があり、その結果、オーバーヘッドが高くなります. . .


SnapCI チームが行ったことは、これらのマイクロサービスを 1 つのモノリスにマージして、システムが実際にどのように実行されているかを理解するための時間を増やすことでした。1 年後、SnapCI チームはこのモノリシック システムをマイクロサービスに再分割し、この分割後、マイクロサービスの境界はより安定しました。この SnapCI の例は、マイクロサービスをパーティショニングする際にドメインの知識が重要であることを示しています。

要約する

マイクロサービスのパーティショニングは、マイクロサービス アーキテクチャのアプリケーション開発において非常に重要です。ドメイン駆動設計の考え方を適用することで、マイクロサービスの分割がドメイン駆動設計のサブドメインの分割に変換され、定義されたコンテキストを通じてドメイン内の概念がモデル化されます。モデル変換は、定義されたコンテキスト間のパターンのマッピングを通じて実行できます。


講義 09: Rapid Deployment 開発環境とフレームワーク

このクラスでは、「迅速な展開の開発環境とフレームワーク」に関するコンテンツを紹介します。


前のクラス時間では、クラウドネイティブ マイクロサービス アーキテクチャに関連する背景知識を紹介しました。次のクラス時間では、実際のマイクロサービス開発に入ります。このクラスは、マイクロサービス開発に関連する最初のクラスであり、ローカル開発環境の準備方法に焦点を当て、サンプル アプリケーションで使用されるフレームワーク、サードパーティ ライブラリ、およびツールを紹介します。

開発に必要

開発前提条件とは、開発環境に必要なものを指します。

ジャワ

サンプル アプリケーションのマイクロサービスは、Java 8 に基づいて開発されています。Java 14 がリリースされたにもかかわらず、サンプル アプリケーションは古いバージョンの Java 8 を引き続き使用します。これは、そのバージョンがまだ広く使用されており、Java 8 の後に追加された新機能がサンプル アプリケーションにとって役に立たないためです。JDK 8 がインストールされていない場合は、 AdoptOpenJDK Web サイトにアクセスして OpenJDK 8 インストーラーをダウンロードすることをお勧めします。MacOS および Linux では、SDKMAN! を使用して JDK 8 をインストールし、さまざまなバージョンの JDK を管理できます。


以下は java -version の出力です。


openjdk バージョン "1.8.0_242" 
OpenJDK ランタイム環境 (AdoptOpenJDK) (ビルド 1.8.0_242-b08) 
OpenJDK 64 ビット サーバー VM (AdoptOpenJDK) (ビルド 25.242-b08、混合モード)

メイヴン

The build tool used by the sample application is Apache Maven. Maven 3.6 を手動でインストールするか、IDE に組み込まれている Maven を使用してプロジェクトをビルドできます。HomeBrewは MacOS と Linux に、 Chocolatey はWindows に推奨されます

統合開発環境

優れた IDE は、開発者の生産性を大幅に向上させることができます。IDEに関しては、主にIntelliJ IDEAとEclipseの2つの選択肢があります.IDEの選択に関しては、両者に大きな違いはありません.私はIntelliJ IDEA Community Edition 2020を使用しています.

ドッカー

ローカル開発環境では、Docker を使用して、データベースやメッセージ ミドルウェアなど、アプリケーションに必要なサポート サービスを実行する必要があります。Docker によって、さまざまなソフトウェア サービスのインストールの問題が解決され、開発環境の構成が非常にシンプルになります。一方、アプリケーションの本番および実行環境は Kubernetes であり、これもコンテナー化を使用してデプロイされ、開発環境と本番環境の間の一貫性が保証されます。ローカルでの開発プロセスを簡素化するために、Docker Compose がローカル環境でコンテナー オーケストレーションに使用されます。


開発環境のOSによって、Dockerのインストール方法が異なります。There are 3 different Docker products that can be used to install Docker, すなわち Docker Desktop, Docker Toolbox and Docker Engine. 次の表は、これら 3 つの製品の適用可能なプラットフォームを示しています。MacOS と Windows の場合、バージョンがサポートしている場合は、最初に Docker Desktop をインストールしてから、Docker Toolbox を検討する必要があります。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/08b546c71c29415aa457b50c722b4952.png#pic_center)


Docker デスクトップ製品は、Docker Engine、Docker Command Line Client、Docker Compose、Notary、Kubernetes、および Credential Helper を含む多くのコンポーネントで構成されています。Docker Desktop の利点は、オペレーティング システムによって提供される仮想化サポートを直接使用できることです, これにより、より良い統合を提供できます. さらに、Docker Desktop はグラフィカル管理インターフェイスも提供します. ほとんどの場合、Docker コマンド ラインから Docker を操作します。docker -v コマンドで正しいバージョン情報が表示されれば、Docker Desktop は正常にインストールされています。


以下の図は、Docker Desktop のバージョン情報を示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/770ba7e74414415baf87f767c182cc16.png#pic_center)


Docker Toolbox は Docker Desktop の前身です。Docker Toolbox は、システム要件の低い仮想化に VirtualBox を使用します。Docker Toolbox は、Docker Machine、Docker Command Line Client、Docker Compose、Kitematic、Docker Quickstart Terminal で構成されています。インストールが完了したら、Docker Quickstart 経由でターミナルを起動して docker コマンドを実行します。


以下の図は、Docker Quickstart ターミナルの実行効果です。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/5bd34c7cfdf446e3b583cd04f0bf2d6e.png#pic_center)


Linux では、Docker Engine を直接インストールすることしかできず、Docker Compose も手動でインストールする必要があります。


Docker Desktop と Docker Toolbox の使用には大きな違いがあります。Docker Desktop で実行されているコンテナーは、現在の開発環境ホストのネットワークを使用でき、コンテナーによって公開されているポートは localhost を使用してアクセスできます; Docker Toolbox で実行されているコンテナーは、実際にアクセスする必要がある VirtualBox の仮想マシンで実行されます。仮想マシンの IP アドレスを介してアクセスします。192.168.99.100 など、Docker Quickstart によって開始された端末で docker-machine ip コマンドを使用して IP アドレスを取得できます。コンテナーによって公開されるポートには、固定されていないこの IP アドレスを使用してアクセスする必要があります。推奨される方法は、hosts ファイルに dockervm という名前のホスト名を追加し、この IP アドレスを指すことです。コンテナ内のサービスにアクセスするときは、常に dockervm ホスト名を使用してください。仮想マシンの IP アドレスが変更された場合、hosts ファイルのみを更新する必要があります。

Kubernetes

アプリケーションをデプロイするときは、利用可能な Kubernetes クラスターが必要です.一般に、Kubernetes クラスターを作成するには 3 つの方法があります。


最初の方法は、クラウド プラットフォームを使用して を作成することです。多くのクラウド プラットフォームが Kubernetes のサポートを提供します. クラウド プラットフォームは Kubernetes クラスタの作成と管理を担当します. ウェブ インターフェースまたはコマンド ライン ツールを使用するだけで、Kubernetes クラスタをすばやく作成できます. クラウド プラットフォームを使用する利点は、時間と労力を節約できることですが、費用がかかります。


2 つ目の方法は、Kubernetes クラスターを仮想マシンまたは物理的なベア メタルにインストールすることです。仮想マシンはクラウドプラットフォームで提供することも、自身で作成・管理することも可能で、自身で維持する物理ベアメタルクラスターを利用することも可能です。RKEKubesprayKubicornなど、オープンソースの Kubernetes インストール ツールが多数あります。この方法の利点は、オーバーヘッドが比較的小さいことですが、欠点は、インストール前とインストール後のメンテナンスが必要になることです。


3 つ目の方法は、ローカルの開発環境に Kubernetes をインストールすることです。Docker Desktop には既に Kubernetes が付属しているので、それを有効にするだけで済みます.さらに、Minikubeをインストールすることもできます. このアプローチの利点は、オーバーヘッドが最も低く、高度に制御できることですが、欠点は、ローカル開発環境で多くのリソースを占有することです。


上記3つの方法のうち、本番環境の導入にはクラウドプラットフォーム方式が適しています。テストおよび配信準備(ステージング)環境は、クラウドプラットフォームを選択するか、コストの観点から環境を自分で構築するかを選択できます。多くの場合、ローカル開発環境上の Kubernetes も必要です。


ローカル開発環境では、Kubernetes for Docker Desktop を手動で有効にする必要があります。Minikube の場合は、公式ドキュメントを参照してインストールできます。この 2 つの違いは、Docker Desktop に付属する Kubernetes のバージョンは、通常、いくつかのマイナー バージョンよりも遅れていることです。下の図に示すように、「Kubernetes を有効にする」オプションをチェックして、Kubernetes クラスターを開始します。Docker Desktop に付属する Kubernetes のバージョンは 1.15.5 で、最新の Kubernetes のバージョンは 1.18 です。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/c7ffd7ae15cf40b8acd4feb80c9d2be6.png#pic_center)

フレームワークとサードパーティ ライブラリ

サンプル アプリケーションでは、いくつかのフレームワークとサードパーティ ライブラリを使用しています。これらについては、以下で簡単に紹介します。

Spring フレームワークと Spring Boot

Spring フレームワークなしで Java アプリケーションを開発することは困難です。Spring Boot は、現在 Java でマイクロサービスを開発するための一般的な選択肢の 1 つでもありますが、Spring と Spring Boot の紹介は、このコラムの範囲を超えています。サンプル アプリケーションのマイクロサービスは、Spring フレームワークのいくつかのサブプロジェクト (Spring Data JPA、Spring Data Redis、Spring Security など) を使用します。

イベントトラム

Eventuate Tram は、サンプル アプリケーションで使用されるトランザクション メッセージ フレームワークです。トランザクション メッセージ モードは、データの一貫性を維持する上で重要な役割を果たします。Eventuate Tram は、トランザクション メッセージング パターンのサポートを提供し、非同期メッセージングのサポートも含みます。Eventuate Tram は、PostgreSQL および Kafka と統合されています。

Axon サーバーとフレームワーク

サンプル アプリケーションではイベント ソーシングと CQRS テクノロジも使用され、イベント ソーシングの実装では Axon サーバーと Axon フレームワークが使用されます。Axon サーバーはイベント ストレージを提供し、Axon フレームワークは Axon サーバーに接続し、CQRS サポートを提供します。

サポート サービスとツール

サンプル アプリケーションのサポート サービスは実行時に必要であり、関連するツールを開発で使用できます。

Apache Kafka と ZooKeeper

サンプル アプリケーションでは、異なるマイクロサービス間で非同期メッセージを使用してデータの最終的な整合性を確保しているため、メッセージ ミドルウェアが必要です。Apache Kafka はサンプル アプリケーションで使用されるメッセージ ミドルウェアであり、Kafka を実行するには ZooKeeper が必要です。

PostgreSQL

サンプル アプリケーションのマイクロサービスの一部は、リレーショナル データベースを使用してデータを格納します。多くのリレーショナル データベースの中で、サンプル アプリケーションの一部のマイクロサービスのデータベースとして PostgreSQL が選択されています。

データベース管理ツール

開発では、リレーショナル データベースのデータを表示する必要がある場合があります。DBeaverpgAdmin 4OmniDBなど、多くの PostgreSQL クライアントが利用可能です。また、IntelliJ IDEA のDatabase Navigatorプラグインなどの IDE プラグインを使用することもできます。

郵便屋さん

In development and testing, we need to send HTTP requests to test REST services. PostmanInsomniaAdvanced REST Clientなど、REST サービスのテストに関連する多くのツールがありますOpenAPI 仕様ファイルを直接インポートして、対応する REST 要求テンプレートを生成できる Postman を使用することをお勧めします。私たちのマイクロサービスは API ファーストの設計アプローチを採用しているため、各マイクロサービス API には対応する OpenAPI 仕様ファイルがあります。開発中は、OpenAPI ファイルを Postman にインポートするだけでテストを開始できるため、手動でリクエストを作成する手間が省けます。

要約する

実際の戦闘について説明する前に、まずローカルの開発環境を準備する必要があります。このクラスでは、最初に Java、Maven、統合開発環境、Docker、および Kubernetes をインストールして構成する方法を紹介し、次にサンプル アプリケーションで使用されるフレームワークとサードパーティ ライブラリを簡単に紹介し、最後にサンプル アプリケーションで使用されるサポート サービスを紹介します。開発に必要なツール。


講義 10: OpenAPI と Swagger を使用した API ファーストの設計

このクラスから始めて、クラウドネイティブなマイクロサービス アーキテクチャ アプリケーションの実際の開発に入ります. マイクロサービスの具体的な実装を紹介する前に、最初のタスクは、各マイクロサービスのオープン API を設計して決定することです. 近年、オープンAPIが広く普及し、多くのオンラインサービスや行政機関がオープンAPIを提供しており、オンラインサービスの標準機能となっています。開発者は、オープン API を使用してさまざまなアプリケーションを開発できます。


マイクロサービス アプリケーションのオープン API とオンライン サービスのオープン API には一定の関係がありますが、機能は異なります。マイクロサービス アーキテクチャのアプリケーションでは、マイクロサービスは通常、REST または gRPC を使用して、プロセス間通信を介してのみ対話できます。このような対話方法は、形式化された方法で修正する必要があり、オープン API を形成します。マイクロサービスのオープン API は、サービスの内部実装の詳細を外部ユーザーから保護し、外部ユーザーがそれと対話する唯一の方法でもあります (もちろん、ここでは API のみを介したマイクロサービス間の統合を指します。統合に非同期イベントが使用されている場合、これらのイベントもインタラクティブです)。このことから、マイクロサービス API の重要性がわかります。聴衆の観点からは、マイクロサービス API のユーザーは主に他のマイクロサービス、つまり主にアプリケーションの内部ユーザーであり、主に外部ユーザー向けのオンライン サービスの API とは異なります。他のマイクロサービスに加えて、アプリケーションの Web インターフェイスとモバイル クライアントもマイクロサービスの API を使用する必要がありますが、通常は API ゲートウェイを介してマイクロサービスの API を使用します。


マイクロサービス API の重要性のため、API を非常に早い段階で設計する必要があります。つまり、API ファースト戦略です。

APIファースト戦略

オンライン サービス API の開発経験がある場合は、通常、実装が最初に行われ、その後にパブリック API が続くことがわかります.これは、パブリック API が設計前に考慮されておらず、後で追加されたためです. このアプローチの結果、オープン API は、API がどうあるべきかではなく、現在の実際の実装のみを反映します。API ファースト (API First) の設計手法は、具体的な実装よりも API の設計を優先するもので、API ファーストでは、API の設計はより API ユーザーの視点から考えるべきであると強調されています。


実装コードの最初の行を書き留める前に、API プロバイダーとユーザーは API について十分に議論し、両者の意見を組み合わせて、最終的に API のすべての詳細を決定し、正式な形式に修正して、 API仕様。その後、API のプロバイダーは実際の実装が API 仕様の要件を満たしていることを確認し、ユーザーは API 仕様に従ってクライアント実装を記述します。API 仕様はプロバイダーとユーザーの間の契約であり、API ファースト戦略は多くのオンライン サービスの開発に適用されています。API が設計および実装された後、オンライン サービス自体の Web インターフェイスとモバイル アプリケーションは、他のサードパーティ アプリケーションと同様に、同じ API を使用して実装されます。


API ファースト戦略は、マイクロサービス アーキテクチャのアプリケーション実装においてより重要な役割を果たします。ここでは、2 種類の API を区別する必要があります。1 つは他のマイクロサービス用に提供される API であり、もう 1 つは Web インターフェイスおよびモバイル クライアント用に提供される API です。第07回の授業でドメイン駆動設計を導入した際に、境界付けられたコンテキストのマッピングモードでオープンホストサービスとパブリック言語について言及しましたが、マイクロサービスは境界付けられたコンテキストに1対1で対応しています。オープンホストサービスと共通言語を組み合わせるとマイクロサービスのAPIとなり、共通言語はAPIの仕様となります。


ここから、最初のタイプのマイクロサービス API の目的はコンテキスト マッピングであることがわかります。これは、2 番目のタイプの API の役割とは大きく異なります。たとえば、乗客管理マイクロサービスは、乗客の登録、情報の更新、クエリなど、乗客を管理するための機能を提供します。旅客アプリの場合、これらの機能には API のサポートが必要です。他のマイクロサービスが旅客情報を取得する必要がある場合は、旅客管理マイクロサービスの API も呼び出す必要があります。これは、異なるマイクロサービス間で乗客の概念をマッピングするためのものです。

API の実装

API の実装において、最初の問題の 1 つは、API の実装方法を選択することです。理論的には、マイクロサービスの内部 API には相互運用性に対する高い要件はなく、プライベート フォーマットを使用できます。ただし、サービス グリッドを使用するためには、共通の標準形式を使用することをお勧めします.次の表に、共通の API 形式を示します。通常、SOAP の使用が少ないことを除いて、REST と gRPC のいずれかを選択します。この 2 つの違いは、REST はテキスト形式を使用し、gRPC はバイナリ形式を使用することであり、この 2 つは人気、実装の難易度、およびパフォーマンスが異なります。つまり、REST は比較的人気があり、実装も難しくありませんが、そのパフォーマンスは gRPC ほど良くありません。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/9e70af995616496b823813f68338f7b6.png#pic_center)


このコラムのサンプル アプリケーションの API は REST を使用して実装されていますが、gRPC 専用のクラスがあります。REST API に関する OpenAPI の仕様について説明します。

OpenAPI 仕様

API プロバイダーとユーザーの間の通信を改善するには、API を記述するための標準形式が必要です。REST API の場合、この標準形式は OpenAPI 仕様で定義されています。


OpenAPI 仕様 (OAS) は、Linux Foundation の下で OpenAPI Initiative (OAI) によって管理されるオープン API 仕様です。OAI の目標は、ベンダー中立の API 記述形式を作成、進化、促進することです。OpenAPI 仕様は、SmartBear Corporation から寄贈された Swagger 仕様に基づいています。


OpenAPI ドキュメントは API を記述または定義しており、OpenAPI ドキュメントは OpenAPI 仕様を満たす必要があります。OpenAPI 仕様は、OpenAPI ドキュメントのコンテンツ形式、つまり、それに含めることができるオブジェクトとその属性を定義します。OpenAPI ドキュメントは、JSON または YAML ファイル形式で表すことができる JSON オブジェクトです。以下は、OpenAPI ドキュメントの形式の概要です。このレッスンのコード例はすべて YAML 形式を使用しています。


OpenAPI 仕様では、整数、数値、文字列、ブール値など、いくつかの基本的な型が定義されています。基本型ごとに、データ型の特定の形式を形式フィールドで指定できます。たとえば、文字列型の形式は、日付、日時、またはパスワードにすることができます。


OpenAPI ドキュメントのルート オブジェクトに表示されるフィールドとその説明を次の表に示します。OpenAPI 仕様の最新バージョンは 3.0.3 です。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/f88b9af5bf5147c7b58c8eb9e7055701.png#pic_center)

情報オブジェクト

Info オブジェクトには API のメタデータが含まれており、ユーザーが API の関連情報をよりよく理解するのに役立ちます。次の表は、Info オブジェクトに含めることができるフィールドとその説明を示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/1b211cd7ab4241dd9bd3649682b9a015.png#pic_center)


次のコードは、Info オブジェクトの使用例です。


タイトル: テスト サービス
の説明: このサービスは簡単なテスト用です
termsOfService: http://myapp.com/terms/ 
contact: 
  name: administrator 
  url: http://www.myapp.com/support 
  email: support@myapp .com
ライセンス:
  名前: Apache 2.0 
  URL: https://www.apache.org/licenses/LICENSE-2.0.html
バージョン: 2.1.0

サーバー オブジェクト

Server オブジェクトは、API のサーバーを表します。次の表は、Server オブジェクトに含めることができるフィールドとその説明を示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/77fca5f8511641c2be4da67d135b5519.png#pic_center)      


次のコードは Server オブジェクトを使用する例です。サーバーの URL には port と basePath の 2 つのパラメーターが含まれ、port は列挙型で、オプションの値は 80 と 8080 です。


URL: http://test.myapp.com:{port}/{basePath}
説明: テスト サーバー
変数:
  ポート:
    列挙型: 
      - '80' 
      - '8080'
    デフォルト: '80' 
  basePath:
    デフォルト: v2

パス オブジェクト

Paths オブジェクトのフィールドは動的です。各フィールドは「/」で始まるパスを表し、パスは変数を含む文字列テンプレートにすることができます。フィールドの値は PathItem オブジェクトです。このオブジェクトでは、summary、description、servers、parameters などの共通フィールドと、get、put、post、delete、options、head、patch、および trace を含む HTTP メソッド名を使用できます。メソッド名フィールドは、対応するパスでサポートされている HTTP メソッドを定義します。

操作対象

Paths オブジェクトでは、HTTP メソッドに対応するフィールドの値の型は、HTTP 操作を表す Operation オブジェクトです。The following table shows the fields and their description that can include in the Operation object. これらのフィールドの中で、パラメーター、requestBody、および応答がより一般的に使用されます。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/762000ab544f4788b74cfdacae07cfc5.png#pic_center)

パラメータ オブジェクト

Parameter オブジェクトは、操作のパラメーターを表します。次の表は、Parameter オブジェクトに含めることができるフィールドとその説明を示しています。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/3d18ce89f02c4331aca232380857786c.png#pic_center)


次のコードは、Parameter オブジェクトの使用例です。パラメータ ID はパスに表示され、その型は文字列です。


名前: ID 
: パス
説明: 乘客ID
必須: true
スキーマ:
  タイプ: 文字列

RequestBody オブジェクト

RequestBody オブジェクトは、HTTP 要求のコンテンツを表します。次の表に、RequestBody オブジェクトに含めることができるフィールドとその説明を示します。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/ac0fc3ca556642349f22f1d039d68267.png#pic_center)

応答オブジェクト

Responses オブジェクトは HTTP 要求への応答を表し、このオブジェクトのフィールドは動的です。フィールドの名前は HTTP 応答のステータス コードであり、対応する値の型は Response オブジェクトまたは Reference オブジェクトです。次の表に、Response オブジェクトに含めることができるフィールドとその説明を示します。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/a3f8790b7b254a8c8795352f36fdb896.png#pic_center)

参照オブジェクト

さまざまなタイプのオブジェクトの説明では、フィールドのタイプを Reference オブジェクトにすることができます。これは、他のコンポーネントへの参照を表し、参照を宣言する $ref フィールドのみを含みます。参照は、同じドキュメント内のコンポーネント、または外部ファイルからのものです。ドキュメント内では、さまざまなタイプの再利用可能なコンポーネントを Components オブジェクトで定義し、Reference オブジェクトによって参照できます。ドキュメント内の参照は、#/components/schemas/CreateTripRequest など、# で始まるオブジェクト パスです。

スキーマ オブジェクト

スキーマ オブジェクトは、データ型の定義を記述するために使用されます。データ型は、単純な型、配列、またはオブジェクト型にすることができます。型はフィールド型によって指定でき、形式フィールドは型の形式を示します。 . 配列型の場合、つまり型の値が配列の場合は、フィールド項目を使用して配列内の要素の型を表す必要があります。オブジェクト型の場合、つまり型の値がオブジェクトの場合は、フィールド項目を使用する必要があります。の場合、フィールド プロパティを使用して、オブジェクト内のプロパティのタイプを表す必要があります。

完全なドキュメントの例

以下は、完全な OpenAPI ドキュメントの例です。paths オブジェクトには 3 つのオペレーションが定義されており、Components オブジェクトの schemas フィールドにはオペレーションのリクエスト内容とレスポンス形式の型定義が定義されています。操作の requestBody フィールドと response フィールドは両方とも、Reference オブジェクトを使用して参照されます。


openapi: '3.0.3'
情報:
  タイトル: 旅行サービスの
  バージョン: '1.0'
サーバー: 
  - URL: http://localhost:8501/api/v1
タグ: 
  - 名前: 旅行の
    説明: 旅行関連の
パス: 
  /:
    投稿:
      タグ: 
        - 旅行
      の概要: 旅行の作成
      operationId: createTrip 
      requestBody:
        コンテンツ:
          アプリケーション/json:
            スキーマ: 
              $ref: "#/components/schemas/CreateTripRequest"
        必須: true      
      応答: 
        '201':
          説明: 正常に作成されました
  /{tripId} :
    取得:
      タグ: 
        - 旅行
      の概要: 旅行の
      操作 ID を取得: getTrip
      パラメーター: 
        - 名前: tripId 
          in: パスの
          説明: 旅行 ID
          が必要: true
          スキーマ:
            タイプ: 文字列
      応答: 
        '200':
          説明: 成功を取得する  
          コンテンツ:
            アプリケーション/json:
              スキーマ: 
                $ref: "#/components/schemas/TripVO" 
        '404': 
          description: Trip not found 
  /{tripId}/accept: 
    post: 
      tags: 
        - trip
      summary: 接受行程
      operationId: acceptTrip
      パラメータ: 
        - name: tripId 
          in: パス
          description: 行程ID 
          required: true 
          schema: 
            type: string 
      requestBody: 
        content: 
          application/json: 
            schema: 
              $ref: "#/components/schemas/AcceptTripRequest" 
        required: true
      応答: 
        '200':
          説明: 受信成功
コンポーネント:
  スキーマ: 
    CreateTripRequest:
      タイプ: オブジェクトの
      プロパティ: 
        PassengerId:
          タイプ: 文字列   
        startPos: 
          $ref: "#/components/schemas/PositionVO" 
        endPos: 
          $ref: "#/components/schemas/PositionVO"
      必須: 
        - PassengerId 
        - startPos 
        - endPos 
    AcceptTripRequest:
        タイプ: オブジェクト
        プロパティ: 
          driverId:
            タイプ: 文字列
          posLng: 
            type: number 
            format: double 
          posLat: 
            type: number 
            format: double
        必須: 
          - driverId 
          - posLng 
          - posLat 
    TripVO:
      タイプ: オブジェクト
      プロパティ: 
        id: 
          タイプ
          :文字
        列
        PassengerId 
        :
          タイプ
          : 文字列 driverId: タイプ
          :
        文字
        列
          type: string                      
    PositionVO: 
      type: object
      プロパティ: 
        lng: 
          type: number 
          format: double 
        lat: 
          type: number 
          format: double  
        addressId:
          タイプ: 文字列 
      必須: 
        - lng 
        - lat

OpenAPI ツール

OpenAPI 仕様に関連する開発を支援するために、いくつかのツールを使用できます。OpenAPI 仕様の前身として、Swagger は OpenAPI に関連する多くのツールを提供します。

Swagger エディター

Swagger Editor は、Swagger および OpenAPI ドキュメント エディターの Web バージョンです。エディターの左側はエディターで、右側は API ドキュメントのプレビューです。Swagger エディターは、構文の強調表示、さまざまな種類のオブジェクトの迅速な追加、サーバー コードの生成、クライアント コードの生成など、多くの便利な機能を提供します。


When using the Swagger editor, you can use the online version directly or run it local. ローカルで実行する最も簡単な方法は、Docker イメージ swaggerapi/swagger-editor を使用することです。


次のコードは、Swagger エディターの Docker コンテナーを開始します。コンテナーが開始されると、localhost:8000 からアクセスできます。


docker run -d -p 8000:8080 swaggerapi/swagger-editor


下の図は、Swagger エディターのインターフェースです。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/a370bf4dc2df4556a6d6298f606058ad.png#pic_center)

Swagger インターフェイス

Swagger インターフェースは、API ドキュメントを表示および操作する直感的な方法を提供します。このインターフェースを介して、HTTP 要求を API サーバーに直接送信し、応答結果を表示できます。


同様に、以下のコマンドに示すように、Docker を使用して Swagger インターフェイスを開始できます。コンテナが起動すると、localhost:8010 からアクセスできます。


docker run -d -p 8010:8080 swaggerapi/swagger-ui


ローカルの OpenAPI ドキュメントについては、そのドキュメントを使用するように Docker イメージを構成できます。現在のディレクトリに OpenAPI ドキュメント openapi.yml があると仮定すると、次のコマンドを使用して Docker イメージを起動し、ドキュメントを表示できます。


docker run -p 8010:8080 -e SWAGGER_JSON=/api/openapi.yml -v $PWD:/api swaggerapi/swagger-ui


以下の図は、Swagger インターフェイスのスクリーンショットです。


![ここに写真の説明を挿入](https://img-blog.csdnimg.cn/fec930f292d7411b90e0b8767b3968b1.png#pic_center)

コード生成

OpenAPI ドキュメントを通じて、Swagger が提供するコード生成ツールを使用して、サーバー スタブ コードとクライアントを自動的に生成できます。コード生成には、さまざまなプログラミング言語とフレームワークを使用できます。


コード生成ツールがサポートするプログラミング言語とフレームワークを以下に示します。


aspnetcore、csharp、csharp-dotnet2、go-server、動的 html、html、html2、java、jaxrs-cxf-client、jaxrs-cxf、インフレクター、jaxrs-cxf-cdi、jaxrs-spec、jaxrs-jersey、
 jaxrs- di, jaxrs-resteasy-eap, jaxrs-resteasy, micronaut , 
spring, nodejs-server, openapi, openapi-yaml, kotlin-client, kotlin-server, php, python, python-flask, r, scala, scala- 
akka -http-server、swift3、swift4、swift5、typescript-angular、javascript


コード生成ツールは、ダウンロード後に直接実行できる Java プログラムです。JAR ファイル swagger-codegen-cli-3.0.19.jar をダウンロードした後、次のコマンドを使用して Java クライアント コードを生成できます。ここで、 -i パラメーターは入力 OpenAPI ドキュメントを指定し、 -l は生成された言語を指定します。 o は、出力の目次を指定します。


java -jar swagger-codegen-cli-3.0.19.jar generate -i openapi.yml -l java -o /tmp


クライアント コードの生成に加えて、サーバー スタブ コードも生成できます。次のコードは、NodeJS サーバー スタブ コードを生成するためのものです。


java -jar swagger-codegen-cli-3.0.19.jar generate -i openapi.yml -l nodejs-server -o /tmp

要約する

API ファースト戦略により、API ユーザーのニーズを十分に考慮してマイクロサービス API が設計され、API がプロバイダーとユーザーの間の適切な契約になります。このクラスでは、最初に API の設計戦略を紹介し、次に API のさまざまな実装方法を紹介し、次に REST API の OpenAPI 仕様を紹介し、最後に OpenAPI の関連ツールを紹介します。


おすすめ

転載: blog.csdn.net/fegus/article/details/124553276