Hanatare's PaPa

Make life a little richer.

Virtual Space of Hanatare's PaPa

人生をほんの少しだけ充実させる

【Architecture】モノリシック vs. 分散システム: 選択の論点

前回の記事ではソフトウェアアーキテクチャの概要とその重要性について紹介をしました。今回の記事では、もう少し掘り下げてソフトウェアアーキテクチャの設計思想について記事にしたいと思います。

www.hanatare-papa.jp

記事のポイント
  • モノリシックアーキテクチャのメリット・デメリット
  • 分散アーキテクチャのメリット・デメリット
  • レイヤードアーキテクチャの特徴とメリット・デメリット
  • モノリシックと分散とレイヤードの違い

モノリシック vs. 分散システム

ソフトウェアアーキテクチャの設計を考えていく上で、「モノリシック」と「分散」という二つの基本的な設計思想の対比があることを理解しておく必要があります。これらはシステムの構成に関する根本的なアプローチの違いを示しており、多くのアーキテクチャパターンはこのいずれかの系譜に連なるか、両者の特徴を組み合わせたものとして位置づけられます 。

モノリシックアーキテクチャ:オールインワンの強力な構造

モノリシックアーキテクチャは、アプリケーションのすべての機能を単一の実行ファイルやデプロイメントユニットとして構築するスタイルです 。ユーザーインターフェース(UI)、ビジネスロジック、データアクセス層といったすべてのコンポーネントが密結合し、一つのプロセスとして実行されます

モノリシックアーキテクチャのメリット

モノリシックアーキテクチャのアプローチは、特に小規模から中規模のプロジェクト、スタートアップの初期製品(MVP)、あるいは要件が明確で安定しているシステムにおいて、多くの利点を提供します。

開発の単純さ

ネットワーク通信の複雑さがなく、すべてのコードが単一のシステム内に存在するため、開発環境の構築が容易です。また、コードも単一のプログラミングやフレームワークになるため、開発チームのスキルセットもシンプルになります。

デバッグとテストの容易さ

すべてのコンポーネントが同じプロセス内で動作するため、スタックトレースの追跡やデバッグが直感的かつ容易に行えます。

デプロイの簡潔さ

生成される成果物は一つであり、環境も少数であることが多いので、デプロイ作業が非常にシンプルです 。

モノリシックアーキテクチャのデメリット

モノリシックアーキテクチャでは、システムが成長し、機能が複雑化するにつれて、モノリシックアーキテクチャは深刻な課題に直面します。

スケーラビリティの課題

アプリケーションの一部に負荷が集中した場合でも、システム全体を複製してスケールさせる必要があり、リソース効率が悪くコストが増大します 。

デプロイのボトルネック

軽微な修正であっても、蜜結合であるがゆえにアプリケーション全体のビルド、テスト、デプロイが必要となり、リリースサイクルが長期化し、デプロイのリスクも増大します。

技術的ロックイン

アプリケーション全体が単一の技術スタックに縛られるため、新しいプログラミング言語やフレームワークの採用が極めて困難になります。

認知的負荷の増大

コードベースが巨大化すると、全体像を把握できる開発者がいなくなり、「巨大な泥団子(Big Ball of Mud)」と呼ばれる、修正や機能追加が困難な状態に陥りがちです 。

分散アーキテクチャ:相互接続されたサービスの世界

分散アーキテクチャは、モノリシックが抱えるスケーラビリティと俊敏性の問題を解決するためのアプローチとして登場しました 。その核心は、巨大なシステムをネットワークを介して通信する、より小さく独立したサービスの集合体として構築することにあります 。

分散アーキテクチャのメリット

分散アーキテクチャは理論上、多くの魅力的な利点を持ちます。

独立したスケーラビリティ

モノリシックアーキテクチャと異なり、各サービスが個別化されたシステムとなっているため、個別の要求に応じてスケールさせることができ、リソースを効率的に利用できます 。

技術の多様性

各サービスに最適なプログラミング言語やデータストアを選択できるため、「適材適所」の技術選定が可能です 。

チームの自律性

サービス単位で開発チームを組織することで、チームは自律的に開発、デプロイを進めることができ、開発速度が向上します。

障害の局所化

一つのサービスの障害がシステム全体に波及することを防ぎ、システムの可用性を高めることができます 。

分散アーキテクチャのデメリット

分散アーキテクチャはその特性上、管理の複雑性などデメリットがあります。その課題は「The Eight Fallacies of Distributed Computing(分散コンピューティングの8つの誤り)」と言われています。ここでは、その8つの誤りについて書いていこうと思います。以下の8つのタイトルはAbly Blogの記事を引用していますので、それぞれ誤りだという前提で確認してください。

ably.com

1. ネットワークは信頼できる (The network is reliable)

ネットワークは決して100%信頼できるものではありません。通信が途切れたり、パケットが失われたり、遅延したりすることは日常的に起こります。そのためネットワークは信頼できないものとして、エラー処理や再試行のロジック対策を行わなければいけません。

2. レイテンシはゼロである (Latency is zero)

データがネットワークを介して送信される際には、必ず遅延(レイテンシ)が発生します。そのため、レイテンシがゼロだと仮定すると応答時間に厳しい要件が求められるシステムで性能問題が発生します。特に、多数の通信を同期的に行う設計は、全体の処理時間を大幅に増加させる可能性があります。

3. 帯域幅は無限である (Bandwidth is infinite)

ネットワークの帯域幅(一度に送れるデータ量)には上限があります。そのため、大量のデータを一度に送信するような非効率な設計はネットワークを逼迫させ、システム全体のパフォーマンス低下を招きます。

4. ネットワークは安全である (The network is secure)

ネットワークは常に盗聴、改ざん、なりすましなどのセキュリティリスクに晒されています。データの暗号化やアクセス制御といったセキュリティ対策を怠ってしまうと、報漏洩や不正アクセスといった重大なセキュリティインシデントを引き起こす可能性があります。

5. トポロジーは変化しない (Topology doesn't change)

ネットワークの構成(トポロジー)は、サーバーの追加や削除、ネットワーク機器の故障などによって動的に変化します。新しいサーバーを追加したり、障害時に構成を変更したりする際に柔軟性が求められます。この柔軟性が失われると、システムの拡張性や可用性が著しく低下する原因となります。

6. 管理者は一人である (There is one administrator)

システムが大規模になると分散システムでは、複数の管理者やチームがそれぞれ異なるコンポーネントを管理・運用します。そのため、設定やポリシー、監視方針を明確にしていなければ、設定誤りなどから問題が発生したり、障害発生時の責任の所在が不明確になります。

7. 輸送コストはゼロである (Transport cost is zero)

データの送受信には、CPUリソースやメモリなど、単なる通信時間以外の計算コスト(シリアライズ・デシリアライズなど)がかかります。このコストを無視すると、頻繁に小さなデータをやり取りするような非効率な通信を多用してしまい、結果としてサーバーのCPU負荷を高め、システムの処理能力を低下させることになります。

8. ネットワークは均質である (The network is homogeneous)

分散システムが接続するネットワークは、性能やベンダーが異なる多様な機器で構成されています。そのため、特定の低速なネットワーク区間が全体のボトルネックになったり、特定のベンダーの機器でしか動作しないといった互換性の問題が発生したりします。

分散アーキテクチャのデメリットまとめ

分散アーキテクチャは管理するシステムが複数に分かれるためシステム間の連携や連携するためのリソース、セキュリティといった面で管理コストが大きくなるという課題があり、 サービスをまたいだデータの一貫性を維持することは非常に困難です。

レイヤード(N層)アーキテクチャ:古典的な関心の分離

これまで、、「モノリシック」と「分散」という二つの基本的な設計思想について説明をしてきましたが、ここで、レイヤードアーキテクチャという考え方を紹介しようと思います。

レイヤードアーキテクチャ(N層アーキテクチャとも呼ばれる)は、ソフトウェアアーキテクチャの中で最も古典的で広く理解されているパターンの一つです。その名の通り、システムを水平な「層(レイヤー)」に分割し、それぞれの層に特定の責務を割り当てます 。

レイヤードアーキテクチャは、モノリシックアーキテクチャにも分散アーキテクチャにも適用できる「設計思想」を表します。

構造と設計思想

「関心の分離(Separation of Concerns)」という設計原則がレイヤードアーキテクチャの根底です。一般的に4つのレイヤーで構成されます。このアーキテクチャの厳格なルールは、依存関係の方向性です。リクエストは上位の層から下位の層へと一方向に流れ、各層は自分よりすぐ下の層にのみ依存します。例えば、プレゼンテーション層はビジネスロジック層に依存しますが、データアクセス層の存在を直接知ることはありません。

プレゼンテーション層 (UI Layer)

ユーザーとのインタラクションを管理し、情報の表示や入力の受け付けを担当します。  

アプリケーション層/ビジネスロジック層 (Business Logic Layer)

システムの中核となるビジネスルールやワークフローを実装します。ドメイン層とも呼ばれます。  

データアクセス層/永続化層 (Data Access Layer)

データベースやファイルシステムといった永続化ストレージとの通信を担います。  

データベース層 (Database Layer)

実際にデータを格納するデータベースそのものを指します。  

レイヤードアーキテクチャのメリット

レイヤードアーキテクチャのメリットには以下があげられます。

高い保守性

各層の責務が明確に分離されているため、開発者は特定の層の修正に集中できます。例えば、UIのデザイン変更がビジネスロジックやデータベースに影響を与えることはありません 。

再利用性

ビジネスロジック層やデータアクセス層を独立したコンポーネントとして開発することで、他のアプリケーションでの再利用が容易になります 。

開発の並行化

各層の入出力インターフェースを定義すれば、異なる開発者がそれぞれの層を並行して開発することが可能です。

レイヤードアーキテクチャのデメリット

レイヤードアーキテクチャのデメリットには以下があげられます。

パフォーマンスの低下

単純なデータの読み書きであっても、リクエストがすべての層を通過する必要があるため、不要なオーバーヘッドが生じ、パフォーマンスが低下する可能性があります 。

陥没穴アンチパターン (Sinkhole Anti-Pattern)

中間層が何のビジネスロジックも持たず、ただリクエストを下の層にそのまま中継するだけ、という状況が発生しがちです。これは不要な複雑性を生み出し、アーキテクチャの価値を損ないます 。

レイヤードアーキテクチャのまとめ

レイヤードアーキテクチャはしばしばモノリシックな実装として紹介されますが、その中核をなす「関心の分離」という原則は、より現代的な分散アーキテクチャにおいても生き続けています。このパターンを単に古いものとして切り捨てるのではなく、アーキテクチャ思考の普遍的な構成要素として理解することが重要です。

モノリシックと分散とレイヤードの違いを整理する

レイヤードアーキテクチャの解説を読むと分散アーキテクチャのようにも感じますし、他のブログ記事を読むとモノリシックアーキテクチャと書いている記事を多く見るかと思います。私も少し混乱をしてしまったので、ここで整理をしておこうと思います。

レイヤードアーキテクチャはアプリケーションの機能の内部構造として層に分けるという考え方(あくまで考え方)になります。

レイヤードアーキテクチャの考え方で機能を層毎に分け、その分けた機能をまとめて1つのアプリケーションの塊として扱う場合は、モノリシックアーキテクチャになります。

レイヤードアーキテクチャの考え方で機能を層毎に分け、その分けた機能毎に分けたアプリケーションとして扱う場合は分散アーキテクチャになります。

モノリシックアーキテクチャであったとしても、デプロイするアプリケーションの構築方法としてレイヤードアーキテクチャの考え方を採用することは非常に多いため、レイヤードアーキテクチャはモノリシックアーキテクチャのように扱われます。

しかし、私の考え方としては、デプロイの単位によってモノリシックなのか、分散なのかをとらえ、中で動くアプリケーション(コード)の作り方としてレイヤードとして考えるのかと捉えるようにすれば良いのかと思っています。

まとめ

前回記事にしたソフトウェアアーキテクチャについて、今回はもう少し掘り下げてモノリシックアーキテクチャと分散アーキテクチャの観点でまとめました。その上で、少し混乱しがちなレイヤードアーキテクチャについても紹介し、それぞれの違いをまとめました。次の記事では、分散アーキテクチャの中をもう少し掘り下げ、昨今人気のマイクロサービスや、イベント駆動、といったアーキテクチャについて記事にしたいと思います。合わせてモノリシックアーキテクチャと分散アーキテクチャのハイブリッドともいえるモノリスモジュラーモノリスについても紹介したいと思います。

次回の記事も読んでいただけると幸いです。