零.Monolithic application から始める
Monolith means composed all in one piece. The Monolithic application describes a single-tiered software application in which different components combined into a single program from a single platform.
(Introduction to Monolithic Architecture and MicroServices Architecture より引用)
ソフトウェアアプリケーションの異なるコンポーネントをすべて 1 つのプログラムに配置することを、Monolithic application と呼びます。例えば、プログラミング言語の基本的な機能を使用してアプリケーションをクラス、関数、名前空間に分割し、デプロイパイプラインを使用して変更が本番環境にデプロイされる前にテストされることを保証し、ロードバランサーの背後で複数のインスタンスを実行して横方向にスケールします:
All your logic for handling a request runs in a single process, allowing you to use the basic features of your language to divide up the application into classes, functions, and namespaces. With some care, you can run and test the application on a developer's laptop, and use a deployment pipeline to ensure that changes are properly tested and deployed into production. You can horizontally scale the monolith by running many instances behind a load-balancer.
このアーキテクチャパターンでは、アプリケーションは適切に機能しますが、2 つの問題があります:
-
変更に制限がある:非常に小さな変更でもアプリケーション全体の再ビルドとデプロイが必要であり、変更の影響範囲を制御するのが難しい
-
スケールが難しい:アプリケーション内でより多くのリソースを必要とする部分のみをスケールすることができず、アプリケーション全体をスケールするしかない
これらの制限はクラウド環境で特に顕著です。そこで、マイクロサービスアーキテクチャが舞台に登場しました
一.マイクロサービスアーキテクチャとは何か?
Microservices are a software development technique—a variant of the service-oriented architecture (SOA) architectural style that structures an application as a collection of loosely coupled services. In a microservices architecture, services are fine-grained and the protocols are lightweight.
(Microservices より引用)
サービス指向アーキテクチャ(SOA)の一種の変種で、アプリケーションを疎結合のサービスのコレクションとして構造化し、軽量な通信プロトコルで組織します
Building applications as suites of services. As well as the fact that services are independently deployable and scalable, each service also provides a firm module boundary, even allowing for different services to be written in different programming languages. They can also be managed by different teams.
具体的には、アプリケーションを一連の小型サービスとして構築します。これらのサービスは独立してデプロイ可能で、独立してスケール可能であり、各サービスは堅固なモジュール境界を持ち、異なるプログラミング言語で異なるサービスを書くこともでき、異なるチームによって管理することもできます

マイクロサービスと SOA
Service-oriented architecture (SOA) is a style of software design where services are provided to the other components by application components, through a communication protocol over a network.
(Service-oriented architecture より引用)
SOA では、サービスはアプリケーションコンポーネントによってネットワーク通信プロトコルを介して他のコンポーネントに提供されます。したがって、マイクロサービスアーキテクチャは SOA の一種の変種、あるいは特定のケースであり、特定の特征を満たす SOA 設計を指します
二.マイクロサービスアーキテクチャの 9 つの特征
サービスによるコンポーネント化(Componentization via Services)
コンポーネントは独立して交換およびアップグレード可能なソフトウェアユニットとして理解でき、一連のコンポーネントを一緒に挿してソフトウェアシステムを構成します。物理世界で見られるものと同様です:
Our definition is that a component is a unit of software that is independently replaceable and upgradeable. There's been a desire to build systems by plugging together components, much in the way we see things are made in the physical world.
マイクロサービスアーキテクチャでは、コンポーネントはサービスです。Web サービスリクエストや RPC などのメカニズムを介して通信します。このサービス粒度のコンポーネント化には 2 つの利点があります:
-
サービスは独立してデプロイ可能
-
サービスは明示的な外部インターフェース(PublishedInterface)を持つ
独立デプロイとは、サービスの内部変更对该サービスのみを再デプロイすればよく、サービスインターフェースの変更が関与する場合のみ複数のサービスの協調変更が必要であることを意味します。另一方面、サービス境界とサービスプロトコルの進化を通じて、このような関連をできるだけ減らすことができます
明示的な外部インターフェースは強力な制約であり、コンポーネントのカプセル化を保証し、コンポーネント間の過度な密結合を避けます
しかし、プロセス内呼び出しと比較して、RPC のパフォーマンスコストはより高く、そのため RPC インターフェースのほとんどは粗粒度であり、しばしば使用がより困難です。另一方面、コンポーネントの責任を調整したい場合、リファクタリングコストもより高くなります
業務機能を中心にチームを組織する(Organized around Business Capabilities)
マイクロサービスは、システムを業務機能に基づいて一連のサービスに分解することを可能にするため、業務機能を中心にクロスファンクショナルなチームを組織することができます。また、この_組織構造はサービス境界の強化にも役立ちます_:

P.S.コンウェイの法則:設計構造は最終的にその組織のコミュニケーション構造と一致します:
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure. -- Melvyn Conway, 1967
コミュニケーション構造が設計構造を変更する非常に興味深い例は、一部のチームがロジックを自分が制御できるアプリケーションに押し込むことです。クロスチームコラボレーションのコミュニケーションコストを避けるためです:
A smart team will optimise around this and plump for the lesser of two evils - just force the logic into whichever application they have access to.
Monolithic application で業務ライン別にチームを分割するのと比較して、サービス境界の方がより明確で、制約力もより強いです。モジュール境界を越えた業務機能が現れやすく、サービス境界は比較的安定しているためです
プロジェクトではなくプロダクトを作る(Products not Projects)
マイクロサービスアーキテクチャは、プロダクトが所属する開発チームによって長期的にメンテナンス/進化されることを好み、プロジェクトがデリバリーされた後に別のメンテナンスチームに引き継がれることを好みません:
Microservice proponents tend to avoid this model, preferring instead the notion that a team should own a product over its full lifetime.
このプロダクト理念は、開発チームとユーザーの間に継続的な関係を構築し、開発チームがソフトウェアがどのようにユーザーを支援して業務機能を向上させるかに注目させます:
There is an on-going relationship where the question is how can software assist its users to enhance the business capability.
スマートエンドポイントとダムパイプ(Smart endpoints and dumb pipes)
通信メカニズムについて、典型的な例は企業サービスバス(Enterprise Service Bus)で、メッセージはすべて ESB を流れ、ESB がメッセージのルーティング、オーケストレーション、変換、およびビジネスルールの適用を担当し、その後エンドポイント(endpoints)に到達して処理されます。このモードでは、エンドポイントはダムに保つことができます。多くのロジックが ESB メッセージパイプ内で処理されるためです。したがって、スマートパイプとダムエンドポイント(smart pipes and dumb endpoints)と呼びます
マイクロサービスはこれとは逆のアプローチを好み、スマートエンドポイントとダムパイプ(smart endpoints and dumb pipes)です:
That the lanes of communication should be stripped of business processing and logic and should literally only distribute messages between components. It's then the components themselves that do processing / logic / validation etc... on those messages.
つまり、パイプはコンポーネント間でメッセージを配信するだけで、サービス自体がメッセージに対して対応する処理を行います
分散型技術ガバナンス(Decentralized Governance)
集中型技術ガバナンスの最大の問題はその制限性で、統一された技術スタックがすべてのシナリオに適しているとは限りません:
Experience shows that this approach is constricting - not every problem is a nail and not every solution a hammer, we prefer using the right tool for the job.
マイクロサービスの背景では、各サービスは個別に構築され、異なる技術スタックを選択する機会があり、より適切なツールを使用して異なることを行うことができます。この技術スタックの自由はサービスの独立した進化に役立ち、自然により良いパターンを選択します
もちろん、「以前は選択がなかったが、今は選択できる」ことは百花繚乱が良いことを意味しません。異なる技術エコシステムをメンテナンスするコストがその収益を上回る可能性があるためです:
We don't end up with 20 different languages in the same system because each of them is opinionated and brings their own vision inside the system, maintaining different ecosystem is very expensive and potentially confusing without providing too many benefits.
权衡之下、我们可以将选择范围限制到某几种技术栈,而不再与一种技术栈强绑定:
But a trade-off could help out, having a limited list of languages or frameworks we can pick from can really help. Suddenly, we are not tightly coupled with one stack only.
分散型データ管理(Decentralized Data Management)
最も抽象的なレベルから見ると、分散型にデータを管理することは、各システムが客観世界に対して形成する概念モデルが異なることを意味します。例えば、営業担当者の眼中的な顧客と開発者が理解する顧客は異なり、同じ概念でも 2 つの視点で微妙な違いがある可能性があります
この状況に対処するための効果的な措置は、ドメイン駆動設計(Domain-Driven Design)の境界付けられたコンテキスト(Bounded Context)です:
应该显式地定义某个模型所应用的上下文。还应该在团队组织、应用中特定部分的使用以及像代码库和数据库模式等物理表现等方面显式地设定边界。要保持边界中模型的严格一致,而不要受外界问题的影响与干扰。
(初窥 Bounded Context より引用)
つまり、モデル概念にコンテキストを限定し、そのコンテキスト内で概念の厳密な一貫性を保証します。複雑なドメインを複数の境界付けられたコンテキストに分割し、それらの間の関連を描き出すことが、概念モデルレベルの分散型 です:
DDD divides a complex domain up into multiple bounded contexts and maps out the relationships between them.
データストレージ的具体化において、マイクロサービスも同様の分散型ポリシーを採用し、各サービスが自分のデータベースを管理する ことを好みます。これらのデータベースは同じデータベース技術の異なるインスタンスでも、完全に異なる���ータベースシステムでもよく、混合持久化 と呼びます:
Microservices prefer letting each service manage its own database, either different instances of the same database technology, or entirely different database systems - an approach called Polyglot Persistence.
P.S.分散型データストレージによってもたらされるデータ一貫性の問題については、いくつかの補償操作を通じてデータを最終的に一貫させることを検討できます。詳細は Starbucks Does Not Use Two-Phase Commit を参照してください
インフラストラクチャの自動化(Infrastructure Automation)
Monolithic application と比較して、マイクロサービスのデプロイはより複雑です。複雑なネットワーク環境では、1 つの独立したアプリケーションをデプロイするよりも複数のサービスをデプロイする方が困難だからです:

しかし、クラウドコンピューティングの発展によりインフラストラクチャの自動化が可能になり、サービスの構築、デプロイ、運用の複雑さを大幅に削減し、インフラストラクチャの自動化を利用して本番環境でのマイクロサービス管理を実現できます
障害に対する設計(Design for failure)
マイクロサービスの背景では、クライアントの耐障害性設計がより重要です:
A consequence of using services as components, is that applications need to be designed so that they can tolerate the failure of services. Any service call could fail due to unavailability of the supplier, the client has to respond to this as gracefully as possible.
Monolithic application と比較して、この耐障害性設計によってもたらされる追加の複雑さは一種の劣勢です
另一方面、障害点を迅速に検出し、可能な限りサービスを自動的に回復させるために、リアルタイムモニタリングもマイクロサービスアーキテクチャで特に重要です
P.S.耐障害性設計の詳細については、Fault Tolerance in a High Volume, Distributed System を参照してください
進化的設計(Evolutionary Design)
コンポーネントの分割はマイクロサービスアーキテクチャで非常に重要で、変化を減らせるかどうかに関係します。一般的な原則は、そのコンポーネントが独立して交換およびアップグレード可能かどうかです:
The key property of a component is the notion of independent replacement and upgradeability.
しかし、別の角度から見ると、変化を制御することは必ずしも変化を減らす必要はありません。これらの変化が予想通りに迅速に行われることを保証できれば、それも非常に優れた制御です:
Change control doesn't necessarily mean change reduction - with the right attitudes and tools you can make frequent, fast, and well-controlled changes to software.
マイクロサービスアーキテクチャが提供するサービスの分解能力をツールとして使用し、これによりサービス粒度の変化制御を実現します:
-
一部のサービスが将来廃止されることを予想し、長期的に進化させる必要はない
-
同時に変化するものを同じサービスに配置し、あまり変化しない部分を個別のサービスに配置し、頻繁に変化する部分と区別する
三.マイクロサービスアーキテクチャの重要な問題
まず、コンポーネント境界を正確に定義することは容易ではありません:
It's hard to figure out exactly where the component boundaries should lie.
したがって、進化的設計は妥協して、境界をより簡単にリファクタリングできるようにします(試行錯誤のコストを削減):
Evolutionary design recognizes the difficulties of getting boundaries right and thus the importance of it being easy to refactor them. But when your components are services with remote communications, then refactoring is much harder than with in-process libraries.
另一方面、設計が良くない場合、これは_コンポーネント内の複雑さをコンポーネント間の接続に移行するだけで、より制御が難しくなります_:
Another issue is If the components do not compose cleanly, then all you are doing is shifting complexity from inside a component to the connections between components. Not just does this just move complexity around, it moves it to a place that's less explicit and harder to control.
このような状況が発生する可能性があります。単一の単純なサービス内部は良く見えますが、サービス間の雑多な接続は無視されます:
It's easy to think things are better when you are looking at the inside of a small, simple component, while missing messy connections between services.
参考資料
-
"マイクロサービス"ブログ中国語翻訳完全版:上記文章の中国語翻訳版
-
[I don't understand micro-frontends.](https://medium.com/ @lucamezzalira/i-dont-understand-micro-frontends-88f7304799a9)
コメントはまだありません