Close

マイクロサービスの構築方法

マイクロサービス アーキテクチャへの移行に関するベスト プラクティス

顔写真: Chandler Harris
Sten Pittet

クラウド アプリの概要


ご利用のアプリケーションは 1 つのコードで構築されており、非常に大規模でモノリシックであるとします。最初はよかったのですが、そのうちうまく機能しなくなりました。あなたはこのアプリケーションを進化させて、さらなる弾力性と拡張性を持たせて独立してデプロイできるようにしたいと考えています。そのためには、細分化されたマイクロサービスのレベルでアプリケーションの構造を再考する必要があります。

アプリケーションの分散化が進んで複雑さが増すにつれて、マイクロサービスの人気が高まってきています。マイクロサービスの指針は、ビジネスのコンポーネントを相互に独立してデプロイして運用できる小規模なサービスに分割することで、アプリケーションを構築することです。サービス間の懸念の分離は「サービスの境界」として定義されます。

サービスの境界は、ビジネス要件と組織階層の境界に密接に関連しています。個々のサービスは、別々のチーム、予算、ロードマップに結びついている場合があります。サービス境界の例としては「決済」と「ユーザー認証」の各サービスが考えられます。マイクロサービスは、すべてのコンポーネントが 1 つになった従来のソフトウェア開発手法とは異なります。

このドキュメントでは「Pizzup」と呼ばれる架空のピザのスタートアップを参照して、マイクロサービスを最新のソフトウェア ビジネスに適用する方法を説明します。

マイクロサービスの構築方法


ステップ 1: モノリスから始める

マイクロサービスの最初のベスト プラクティスは、おそらくそれは不要だということです。アプリケーションのユーザーがいなければ、MVP の構築中にビジネス要件が急速に変化する可能性があります。これは、単にソフトウェア開発の性質と、システムが提供する必要のある主要なビジネス機能の特定中に発生する必要があるフィードバック サイクルによるものです。マイクロサービスでは、管理の負担と複雑さが指数関数的に増加します。このため、すべてのコードとロジックを単一のコードベース内に保持する方がアプリケーションのさまざまなモジュールの境界を移動しやすいため、新しいプロジェクトの負担が遥かに軽くなります。

たとえば、Pizzup では解決したい単純な問題から始めます。顧客がオンラインでピザを注文できるようにしたい、などです。

「ユーザーとしてピザをオンラインで注文できる!」と言っている Pizzup ユーザー
アイコン: code-store
関連資料

マイクロサービスとモノリシック アーキテクチャの比較

アイコン: 3 つの輪
ソリューションを見る

Compass によってコンポーネントを管理

ピザ注文の課題について考え始めるにあたって、そのニーズを満たすためにアプリケーションで必要なさまざまな機能を特定します。作れるさまざまなピザのリストを管理できるようにしたり、顧客が 1 枚以上のピザを選んで決済し、配達のスケジュールなどをできるようにする必要があります。顧客にアカウントを作成してもらうことで、次に Pizzup を利用するときに簡単に注文できるようにするという発想もあります。最初の利用者との対話によって、配達のライブ追跡とモバイル サポートを提供すれば競合他社より優位に立てるということがわかる可能性があります。

Pizzup アプリのエンド ユーザーと管理者の使用法の違いを示すグラフィック。

開始時には単純なニーズだったのが、すぐに新機能が並ぶリストに変わりました。

マイクロサービスは、システムが必要とするさまざまなサービスを十分に把握している場合に適しています。しかし、アプリケーションのコア要件がまだしっかりと定義されていない場合、マイクロサービスはずっと扱いにくくなります。マイクロサービスのサービス間の相互作用、API、データ構造を再定義することは、一般的に多くの不確定要素を調整する必要があるため非常にコストがかかります。そのため、十分なユーザー フィードバックを収集して顧客の基本的なニーズを理解して計画していることを確信できるまで、物事をシンプルに保つことをお勧めします。

しかし、注意点として、モノリスを構築するとすぐにコードが複雑になって、細かく分解するのが難しくなってしまいます。後でモノリスから抽出できるように、モジュールを明確に特定するとよいでしょう。また、Web UI からロジックを分離して、HTTP による RESTful API を介したバックエンドとの相互作用を確認することからも始められます。これによって、将来的に API リソースを別のサービスに移動する際に、マイクロサービスへの移行が容易になります。

ステップ 2: チームを正しく編成する

ここまでは、マイクロサービスの構築はほとんど技術的な問題のように見えたことでしょう。たとえば、コードベースを複数のサービスに分割し、故意に失敗してネットワークの問題から回復するための適切なパターンを実装し、データの一貫性を確保し、サービス負荷を監視する必要がある、などです。把握するべき新しい概念がたくさんあります。しかし、無視してはならないのは、チームの編成方法を再構築する必要があるということです。

コンウェイの法則は真実であり、あらゆるタイプのチームで観察されます。ソフトウェア チームがバックエンド チーム、フロントエンド チーム、運用チームで編成されて、それぞれが独立して作業している場合は、フロントエンドとバックエンドのモノリスが別々に作成されて大したコミュニケーションもないままに運用チームに渡され、本番環境に移ります。このタイプのチーム構造はマイクロサービスには適していません。なぜなら、各サービスは独自の製品として扱われて、他のサービスとは独立してリリースされる必要があるためです。

代わりに、担当しているサービスの開発と維持に必要なすべての能力を持つ、小規模な DevOps チームを作る必要があります。この方法でチームを編成するのには、大きなメリットがあります。まず、開発者が本番環境におけるコードの影響をより深く理解します。これによって、より質の高いリリースが作成されて、問題が顧客にリリースされるリスクを軽減できます。次に、コードの改善とデプロイ パイプラインの自動化にすべてのチームが一緒になって取り組むため、各チームが当然の習慣としてデプロイを行うようになります。

ステップ 3: モノリスを分割してマイクロサービス アーキテクチャを構築する

サービスの境界を特定してチームの再構築方法を理解したら、モノリスを分割してマイクロサービスの構築を始められます。その時に考える重要なポイントは次のとおりです。

RESTful API でサービス間の通信をシンプルに保つ

まだ RESTful API を使用していない場合は、今が採用の好機です。Martin Fowler は、ユーザーには「賢いエンドポイントと愚直なパイプ」が必要と説明しています。つまり、データを変換せずに送信するだけなど、サービス間の通信プロトコルはできる限りシンプルでなければなりません。魔法はエンドポイント自体で起こります。エンドポイントはリクエストを受け取って処理し、回答を返します。

マイクロサービス アーキテクチャは、コンポーネントの緊密な結合を避けるためにできるだけ物事を単純に保とうとします。場合によっては、非同期メッセージベースの通信でイベントドリブン アーキテクチャを使用していることがあります。しかし、もう一度 RabbitMQ のような基本的なメッセージ キュー サービスを調べて、ネットワーク経由で送信されるメッセージが複雑にならないようにする必要があります。

境界づけられたコンテキストまたはデータ ドメインにデータを分割する

モノリス アプリケーションは、アプリケーションのすべてのビジネス機能に対して単一のデータベースを使用します。モノリスをマイクロサービスに分割すると、この単一のデータベースはもはや意味をなさない可能性があります。中央データベースは、増加するトラフィックのボトルネックになる可能性があります。特定のサービスがデータベースに高い負荷をかけると、他のサービスがデータベースにアクセスできなくなる場合があります。さらに、複数のチームが同時にスキーマを変更しようとすると、単一のデータベースがコラボレーションのボトルネックになる可能性があります。したがって、マイクロサービスのデータ ニーズに対応するには、データベースの分割やデータ ストレージ ツールの追加が必要になる場合があります。

モノリシック データベース スキーマのリファクタリングは、デリケートな操作になる可能性があります。各サービスに必要なデータセットと重複するデータセットを明確に特定することが重要です。このスキーマ プランニングは、ドメイン駆動設計のパターンである境界づけられたコンテキストによって実行できます。境界づけられたコンテキストは、システムへの入出力情報を含む自己完結型のシステムを定義します。

このシステムでは、ユーザーが注文にアクセスする際に顧客情報を確認するのと同じテーブルから、請求システムで管理される請求書にデータを入力できます。これは論理的で単純に見えますが、マイクロサービスでは発注システムがダウンしていても請求書にアクセスできるように、これらのサービスを分離する必要があります。これによって、請求書テーブルを他のテーブルとは無関係に最適化または進化できます。つまり、各サービスが必要なデータにアクセスできるようにするために、それぞれ独自のデータストアを持つことになる可能性があります。

これによって、一部のデータがデータベース間で重複するために新たな問題が発生します。境界づけられたコンテキストによって、共有または重複データを処理するための最適な戦略が見つかります。イベントドリブン アーキテクチャを採用すれば、複数のサービス全体でデータを同期できます。たとえば、顧客が個人情報を更新した際にアカウント サービスから発生するイベントを請求と配達追跡の各サービスでリッスンするようにします。これらのサービスは、イベントを受信するとそれに応じてデータストアを更新します。このイベントドリブン アーキテクチャでは他のすべての依存サービスは理解不要なため、アカウント サービス ロジックをシンプルに保てます。サービスは実行した内容を単にシステムに伝えて、他のサービスはそれをリッスンして必要に応じて動作します。

また、すべての顧客情報をアカウント サービスに保存して、外部キー参照のみを請求と配達サービスに保持できます。その後、既存のレコードを複製する代わりに、アカウント サービスとやり取りして関連する顧客データを取得できます。これらの問題に対する普遍的な解決策はないので、それぞれの特定のケースを調べて何が最良のアプローチかを判断する必要があります。

障害に備えたマイクロサービス アーキテクチャの構築

どのようにマイクロサービスがモノリシック アーキテクチャよりも大きなメリットを実現できるかを見てきました。サイズが小さく機能が特化されたマイクロサービスは、分かりやすさも突出しています。マイクロサービスは切り離されているため、システムの他のコンポーネントを壊したり他のチームの開発を遅らせたりするのを恐れることなく、サービスをリファクタリングできます。また、他のサービスのニーズに制約されることなく必要に応じてさまざまなテクノロジーを選択できるため、開発者の柔軟性が高まります。

要するに、マイクロサービス アーキテクチャを持つことで、各ビジネス機能を簡単に開発して維持できるようになります。しかし、すべてのサービスを俯瞰してどのように相互作用させればアクションを実行できるかを考えると、物事はより複雑になります。システムには複数の障害点が存在し、それに対応する必要があります。サービスが応答しないケースについて考えるだけでなく、ネットワーク応答の遅延に対処できる必要があります。障害からの回復も時には難しい可能性があります。復旧後に稼働したサービスが保留中のメッセージによってフラッディングしないようにする必要があるためです。

モノリシック システムから機能を抽出し始めるときは、最初から障害を考慮した設計になっていることをご確認ください。

マイクロサービスのテストを容易にするために監視を重視する

テストは、モノリシック システムと比較した際のマイクロサービスのもう 1 つの欠点です。単一のコードベースとして構築されるアプリケーションは、テスト環境を稼働させる必要はそこまでありません。ほとんどの場合、テスト スイートを実行できるようにするには、データベースと一体化されたバックエンド サーバーを起動する必要があります。

マイクロサービスの世界では、物事はそんなに簡単ではありません。ユニット テストに関しては、モノリスとあまり違いがなくそれほど難しくありません。しかし、統合とシステム テストに関しては、物事は遥かに難しくなります。複数のサービスをまとめて起動して、さまざまなデータストアを稼働させなければならない場合があります。また、モノリスでは不要なメッセージ キューをセットアップに含めなければならない場合があります。このような状況では、機能テストの実行には遥かにコストがかかります。不確定要素の数が増えると、起こり得るさまざまなタイプの障害を予測することは非常に困難になります。

監視によって、問題を早期に特定して適切に対応できます。さまざまなサービスの基準を理解することで、サービスがダウンしたときだけでなく予期せぬ動作をしているときにも反応できるようにする必要があります。マイクロサービス アーキテクチャを導入するメリットの 1 つとして、システムが部分的な障害に対して耐障害性があることがあげられます。これによって、Pizzup アプリの配達追跡サービスに異常が見え始めても、モノリシック システムほど悪い状況には陥らないでしょう。アトラシアンのアプリケーションは、他のすべてのサービスが適切に反応することで、ライブトラッキングを復元しながら顧客からのピザ注文を受け付けられるように設計する必要があります。

継続的なデリバリーを活用してデプロイの摩擦を軽減する

モノリシック システムを本番環境に手動でリリースすることは面倒で危険な作業ですが、できることです。もちろん、このアプローチはお勧めしません。すべてのソフトウェア チームがあらゆる種類の開発で継続的なデリバリーを活用することを推奨しますが、プロジェクトの開始時にはコマンド ラインによって最初のデプロイを自分で行う場合があります。

1 日に複数回デプロイする必要があるサービスの数が増えている際は、このアプローチは持続可能ではありません。したがって、マイクロサービスへの移行の一環として、リリース障害のリスクを軽減するために継続的なデリバリーを活用して、さらにチームがアプリケーションのデプロイに立ち往生するのではなく、アプリケーションの構築と実行に集中できるようにすることが重要です。また、継続的なデリバリーの実践は、本番環境への移行前にサービスが受け入れテストに合格したことを意味します。もちろんバグは発生しますが、時間の経過とともに堅牢なテスト スイートが構築されて、リリースの品質に対するチームの自信が高まります。

マイクロサービスの実行はスプリントではない


マイクロサービスは、急速に普及して広く採用されている業界のベスト プラクティスです。複雑なプロジェクトでも、柔軟にソフトウェアを構築してデプロイできます。また、システムのビジネス コンポーネントの識別と形式化にも役立ちます。これは、複数のチームが同じアプリケーションに取り組んでいる際に便利です。しかし、分散型システムの管理には明らかな欠点もあります。モノリシック アーキテクチャの分割は、サービスの境界を明確に理解している際にのみ行う必要があります。

マイクロサービスの構築は、チームの直近の目標ではなくジャーニーとして捉える必要があります。小規模から始めて、分散型システムの技術要件、故意の失敗、個々のコンポーネントを拡張する方法を理解しましょう。その後、経験を積んで知識を得るにつれ、徐々により多くのサービスを抽出できます。

マイクロサービス アーキテクチャへの移行は、1 つの包括的な努力で達成する必要はありません。小規模なコンポーネントをマイクロサービスに順次移行する反復戦略の方がより確実です。確立されたモノリス アプリケーション内で最も明確に定義されたサービス境界を特定して、それらを独自のマイクロサービスに分離するように反復して取り組みます。

結論


要約すると、マイクロサービスは、生の技術コード開発プロセスと全体的なビジネス組織戦略の両方にとってメリットのある戦略です。マイクロサービスは、特定のビジネス機能の開発と所有に重点を置いたチーム編成に役立ちます。このように細分化して重点的に取り組むことで、ビジネス全体のコミュニケーションと効率性が向上します。マイクロサービスのメリットには犠牲が伴います。マイクロサービス アーキテクチャに移行する前に、サービスの境界を明確に定義することが重要です。

マイクロサービス アーキテクチャには多くのメリットがありますが、複雑さも増します。アトラシアンが開発した Compass は、分散型アーキテクチャの規模が拡大するにつれて増す複雑さを管理するために役立ちます。Compass は、拡張可能な開発者エクスペリエンス プラットフォームです。これによって、すべてのエンジニアリング成果とチーム コラボレーションに関する分断された情報を、一元化された検索可能な場所にまとめられます。

Sten Pittet
Sten Pittet

私はソフトウェアビジネスに 10 年間携わり、開発からプロダクトマネージメントまでさまざまな業務を経験してきました。アトラシアンで 5 年間開発ツールに携わった後、現在はソフトウェアの構築について記事を書いています。プライベートではかわいい赤ちゃんと過ごしながら、父親力を磨いています。


この記事を共有する

おすすめコンテンツ

次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。

DevOps のイラスト

Compass コミュニティ

イラスト: 障害の克服

チュートリアル: コンポーネントを作成する

マップのイラスト

Compass を無料で始める

DevOps ニュースレター購読

Thank you for signing up