はじめに: マイクロサービスの危機
Il 組織の 42% マイクロサービス アーキテクチャを放棄または簡素化しています。 このデータはセクターレポートから明らかになり、Amazon、Uber、Twitter などの企業の経験によって確認されました。 ソフトウェア アーキテクチャの歴史の転換点を示します。制御不能な熱意が10年間続いた後、 セクターはついにこの問題に同意しつつある 隠れたコスト 配布の。
このシリーズの最初の記事では 「マイクロサービスからモジュラーモノリスへ」、信号を分析します マイクロサービス アーキテクチャが解決策ではなく問題になりつつあることを示す警告サイン、 実際の失敗例を見てご紹介します。 モジュラーモノリス 実用的な代替案として。
この記事で学べること
- 機能不全のマイクロサービス アーキテクチャの 5 つの警告サイン
- マイクロサービスの隠れたコスト: インフラストラクチャ、レイテンシ、運用の複雑さ
- 実際のケーススタディ: Amazon Prime Video、Twitter、セグメント
- スケーラビリティの誤謬: 本当に個別にスケーリングする必要がない場合
- マイクロサービスと代替サービスのどちらを選択するための意思決定フレームワーク
- 新たなパラダイムとしてのモジュール式モノリスの紹介
分散モノリス: 考えられる最悪のシナリオ
マイクロサービスを導入した多くの組織は、実際に次のような問題に直面しています。 分散型モノリス: モノリスの欠点 (密結合、調整された展開) とモノリスの欠点を組み合わせたシステム。 導入 (ネットワーク遅延、運用の複雑さ、困難なデバッグ)。そして最悪のアーキテクチャシナリオ 可能です。
分散モノリスは、次の特性によって認識できます。
- 同期された展開: 他の 3 ~ 4 つのサービスもアップグレードしないとサービスをデプロイできません
- 共有データベース: 複数のサービスが同じテーブルにアクセスし、データレベルの結合を作成します。
- 同期呼び出しをチェーンする: ユーザー リクエストは完了するまでに 5 ~ 8 つのサービスを通過します。
- ブロックされたチーム: サービス間の依存関係により、チームが独立して作業することが妨げられます
// Esempio di distributed monolith: OrderService dipende da 4 servizi
public class OrderService {
private final UserServiceClient userClient;
private final InventoryServiceClient inventoryClient;
private final PaymentServiceClient paymentClient;
private final NotificationServiceClient notificationClient;
public Order createOrder(CreateOrderRequest request) {
// Chiamata sincrona 1: verifica utente
User user = userClient.getUser(request.getUserId());
// Chiamata sincrona 2: verifica disponibilità
InventoryCheck check = inventoryClient.checkAvailability(
request.getItems()
);
// Chiamata sincrona 3: processa pagamento
PaymentResult payment = paymentClient.processPayment(
user, request.getTotal()
);
// Chiamata sincrona 4: invia notifica
notificationClient.sendOrderConfirmation(user, order);
// Se un qualsiasi servizio e giù, l'intero flusso fallisce
return order;
}
}
この例では、 OrderService 4 つの異なるサービスに対して同期依存関係があります。一つでもあれば
彼がそれらに応答しないだけで、秩序を生み出すプロセス全体が失敗します。これらはマイクロサービスではありません
独立型: ネットワーク上に分散されたモノリスです。
5つの警告サイン
マイクロサービス アーキテクチャが 1 つのアーキテクチャになりつつあることを示す 5 つの重要な指標があります。 資産ではなく負債です。早期に問題を認識することで、数か月の作業と大幅な予算を節約できます。
1. 複雑さの過負荷
サービスの数がチームの管理能力を超えると、複雑さが制御できなくなります。 40 のマイクロサービスを管理する 15 人の開発者チームには、維持、監視、および実行するための帯域幅がありません。 すべてのサービスを適切に更新してください。理想的な関係は、 開発者あたり最大 2 ~ 3 つのサービス、 そしてこれはすでに最適な状態にあります。
複雑さは、サービス メッシュ構成、TLS 証明書の管理などの具体的な形で現れます。 サービス間、内部 API のバージョン管理、チーム間の契約管理。追加サービス 複雑さが大幅に増加する 非線形.
2. モノリスと比較してコストが 6 倍
業界調査によると、マイクロサービス アーキテクチャの運用コストは平均して 6倍高い 同等のモノリスと比較して。これには以下が含まれます。
- インフラストラクチャー: 各サービスには独自のコンテナ、ロードバランサ、ヘルスチェックが必要です
- 可観測性: 分散トレース、ログ集約、サービスごとのメトリクス
- ネットワーキング: サービスメッシュ、APIゲートウェイ、サーキットブレーカー
- チーム: 専任の DevOps、プラットフォーム チーム、専門の SRE
# Esempio: risorse Kubernetes per UN singolo microservizio
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
template:
spec:
containers:
- name: order-service
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
---
# Servono anche: Service, Ingress, HPA, PDB,
# ConfigMap, Secret, ServiceMonitor, NetworkPolicy...
# Moltiplica per 20+ servizi = complessità enorme
3. 持続不可能な運用上のオーバーヘッド
各マイクロサービスには、専用の CI/CD パイプライン、モニタリング、アラート、 依存関係の管理、セキュリティパッチの適用。 30 のサービスがある場合、30 のパイプライン、30 セットを維持する必要があります。 構成するアラートの数、更新する必要のある dockerfile の数は 30 です。で過ごした時間 オペレーション 超える 専用のもの 機能開発.
4. 遅延の増加
サービス間の呼び出しごとにネットワーク遅延が発生します。 5つのサービスにまたがるリクエストが蓄積される 5 ネットワーク ホップの遅延、シリアル化/逆シリアル化時間、および サービス検出ルックアップ。モノリスでは、同じ操作がメソッド呼び出しとなります。 次のようなレイテンシーを伴う処理中 ナノ秒.
5. 分散型脆弱性
分散システムでは、障害は例外ではなく標準です。あらゆるコミュニケーションポイント サービスと潜在的な障害点の間。サーキット ブレーカー、バックオフ付きの再試行、タイムアウト、 フォールバック: これらは必要なパターンですが、アプリケーション コードが大幅に複雑になります。
常識の法則
チームが以上の費用を費やした場合、 40%の確率で 運用活動 (展開、デバッグ、 インフラストラクチャ構成)、機能開発ではなく、アーキテクチャは あなたのためではなく、あなたに不利に働くのです。アーキテクチャの選択を再評価する時期が来ています。
ケーススタディ: ジャイアンツが帰ってくるとき
大手テクノロジー企業の経験は、分散型から社会への回帰が実証されています。 統合されたことは弱さの兆候ではなく、エンジニアリングの成熟度の兆候です。
Amazonプライム・ビデオ
2023 年、Amazon Prime Video チームはその好例として、 ビデオ品質モニタリング、最初はマイクロサービス パイプラインで構築されました サーバーレス (AWS Step Functions + Lambda)、および状態 単一のプロセスに統合される。 結果?コストの削減 90% そして大幅な改善 スケーラビリティ。ボトルネックはアプリケーション ロジックではなく、オーケストレーションのオーバーヘッドでした 分散コンポーネント間。
ツイッター(X)
2022 年の買収後、エンジニアリング チームはマイクロサービスの数を大幅に削減しました。 機能をより大きなサービスに統合し、間接層を削除します。それにもかかわらず 会社経営上の意見から、技術的には大幅な削減効果が得られた インフラストラクチャのコストと運用の簡素化を実現します。
セグメント
顧客データ プラットフォームである Segment は、マイクロサービスから戻ったエクスペリエンスを文書化しました。 モノリスへ。 140 を超えるマイクロサービスが比較的小規模なチームによって管理されているため、 維持管理が不可能になってしまいました。より確立されたアーキテクチャへの移行により、 導入時間の短縮80% そしてチームの運営負荷 60%.
スケーラビリティの誤謬
マイクロサービスを支持する最も一般的な議論は次のとおりです。 独立したスケーラビリティ:可能性 必要なサービスのみを拡張します。しかし、本当に必要な組織はどれくらいあるのでしょうか 個々のコンポーネントをさまざまなレベルにスケールしますか?
実際には、ほとんどのシステムでは次のようなことが起こります。
- Il トラフィックの 80% エンドポイントの 20% に影響
- Il データベース そしてほとんどの場合、本当のボトルネックはコンピュータではありません
- 適切に最適化された単一のプロセスがそれを処理します 毎秒数千のリクエスト
- モノリス水平スケーリング (ロード バランサーの背後にある複数のインスタンス) でケースの 95% をカバー
// La maggior parte delle applicazioni non ha bisogno
// di scaling indipendente per servizio.
// Un monolith scalato orizzontalmente e sufficiente:
// Scenario: 10.000 richieste/secondo
// Monolith: 4 istanze x 2.500 req/s ciascuna
// Microservizi: 20 servizi x 3 istanze = 60 container
// Costo monolith: 4 container x $50/mese = $200/mese
// Costo microservizi: 60 container x $30/mese = $1.800/mese
// + Load balancer, service mesh, monitoring = $500/mese
// Totale microservizi: ~$2.300/mese (11.5x più costoso)
意思決定の枠組み: いつ何を選択するか
普遍的に最適なアーキテクチャは存在しません。選択は特定の状況に応じて異なります 組織の。客観的な基準に基づいた意思決定の枠組みは次のとおりです。
マイクロサービスを選択する場合
- あなたが持っている 大規模なチーム (50 人以上の開発者) 完全な自主性を必要とする人
- 要件を満たしています 極端なスケーリング (数百万リクエスト/秒) コンポーネント間で負荷パターンが大きく異なる場合
- あなたが持っている 異種の技術要件: 異なる言語またはランタイムを必要とするコンポーネント
- あなたは 成熟した DevOps/プラットフォーム チーム インフラに特化した
- Il 市場投入までの時間 各機能はチーム間の独立性に依存します
モノリス (モジュラー) を選択する場合
- あなたは 中小規模のチーム (開発者 3 ~ 30 人)
- あなたの製品は次のとおりです 初期または成長期 そしてその境界線はまだ明確ではない
- 必要がある 迅速な反復 導入の簡素化
- インフラストラクチャの予算 限定
- 必要がある 強い一貫性 コンポーネント間 (ACID トランザクション)
黄金律
常にモジュラーモノリスから始めてください。マイクロサービスがある場合にのみ抽出する それを正当化する具体的なデータ: 負荷メトリック、測定されたボトルネック、 特定のスケーリングが必要な場合。マイクロサービスの早期抽出が原因の 1 つ アーキテクチャ上の失敗の主な原因。
モジュラーモノリスの概要
Il モジュラーモノリス 両方の長所を組み合わせたアーキテクチャ: シンプルさ マイクロサービスの論理モジュール性を備えたモノリスの操作。単一のデプロイ可能なアーティファクト 明確な境界、明確に定義された内部 API、およびデータ所有権を持つ独立したモジュールが含まれています モジュールごとに。
このアーキテクチャには、すぐに次のような利点があります。
- シンプルな導入: 単一のアーティファクト、1 つのパイプライン、サービス間の調整は不要
- 直接デバッグ: フルスタックトレース、分散トレースは不要
- ACIDトランザクション: プロセス内での一貫性が保証されています
- 安全なリファクタリング: コンパイラはモジュール間のインターフェイスをチェックします。
- 将来の抽出: モジュールは必要に応じてマイクロサービスになることができます
// Struttura di un modular monolith in Java/Spring Boot
// Ogni modulo ha il proprio package con boundaries chiare
// com.app.order/ (modulo Order)
// ├── api/ -> interfacce pubbliche del modulo
// ├── internal/ -> implementazione privata
// ├── domain/ -> entità e logica di dominio
// └── infrastructure/ -> persistenza, eventi
public interface OrderModuleApi {
OrderDto createOrder(CreateOrderCommand cmd);
OrderDto getOrder(UUID orderId);
List<OrderDto> getOrdersByUser(UUID userId);
}
// L'implementazione e nascosta nel package internal
class OrderModuleImpl implements OrderModuleApi {
private final OrderRepository orderRepo;
private final EventPublisher eventPublisher;
public OrderDto createOrder(CreateOrderCommand cmd) {
Order order = Order.create(cmd);
orderRepo.save(order);
eventPublisher.publish(new OrderCreatedEvent(order.getId()));
return OrderDto.from(order);
}
}
次の記事で説明する内容
このシリーズの 8件の記事 理解から完全な旅へとあなたを導きます 実際の移行に向けた問題の解決:
- 第2条: モジュラーモノリスの詳細なアーキテクチャ、モジュール境界、内部 API、Spring Modulith
- 第3条: モジュール境界を定義するための境界付きコンテキストと DDD
- 第4条: データベース設計、モジュールと共有スキーマ、データの所有権
- 第5条: 通信パターン: インプロセス イベント、メディエーター、CQRS
- 第6条: インテリジェントな導入とスケーリング、機能フラグ、青と緑
- 第7条: 従来のモノリスからモジュラーモノリスへの段階的な移行
- 第8条: 定量化された ROI と前後の指標を使用したケーススタディ
次の記事
次の記事では、以下について詳しく説明します。モジュラーモノリスのアーキテクチャ: モジュール間の境界を定義する方法、内部 API を設計する方法、フレームワークの仕組み ばね弾性率 時間の経過とともに境界を維持するのに役立ちます。合格します アーキテクチャ図とリファレンス コードを使用して理論から実践まで。







