- Published on
マイクロサービスアーキテクチャ2025完全ガイド:モノリスからMSA、そしてモジュラーモノリスへ
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- はじめに
- 1. アーキテクチャの進化:モノリスからモジュラーモノリスまで
- 2. MSAが過剰な場合:反省と教訓
- 3. モジュラーモノリス深堀り
- 4. DDD基盤のサービス分解戦略
- 5. 通信パターン:同期 vs 非同期
- 6. Service Mesh比較と実践
- 7. 分散トランザクション:Sagaパターン
- 8. オブザーバビリティ:OpenTelemetryスタック
- 9. API Gatewayパターン
- 10. デプロイ戦略
- 11. マイグレーション戦略:モノリスからMSAへ
- 12. アンチパターン:これだけは避けよう
- 13. 意思決定フレームワーク
- 14. 面接対策:マイクロサービス核心質問20選
- 15. クイズ
- 参考資料
はじめに
2025年(ねん)、ソフトウェアアーキテクチャの状況(じょうきょう)が再(ふたた)び変(か)わりつつあります。2010年代(ねんだい)中盤(ちゅうばん)にNetflixとAmazonが主導(しゅどう)したマイクロサービスブーム以降(いこう)、多(おお)くの企業(きぎょう)がMSAを導入(どうにゅう)しましたが、その多(おお)くが「分散(ぶんさん)モノリス(Distributed Monolith)」という最悪(さいあく)の結果(けっか)に直面(ちょくめん)しました。
DHH(Ruby on Rails創設者(そうせつしゃ))の「Majestic Monolith」宣言(せんげん)、Amazon Prime Videoチームの MSAからモノリスへの回帰(かいき)、Segmentのマイクロサービス撤回(てっかい)— これらの事例(じれい)は業界(ぎょうかい)に強力(きょうりょく)なメッセージを送(おく)りました。アーキテクチャはチームの規模(きぼ)と問題(もんだい)の複雑度(ふくざつど)に合(あ)わせるべきだということです。
このガイドでは、モノリスからSOA、MSA、そして2025年(ねん)のトレンドであるモジュラーモノリスまで、アーキテクチャの全(ぜん)スペクトラムを扱(あつか)います。サービス分解戦略(せんりゃく)、通信(つうしん)パターン、Service Mesh、分散(ぶんさん)トランザクション、オブザーバビリティ、API Gateway、デプロイ戦略(せんりゃく)、マイグレーションパターン、アンチパターンまで — マイクロサービスに関(かん)する全(すべ)てを整理(せいり)します。
1. アーキテクチャの進化:モノリスからモジュラーモノリスまで
1.1 モノリシックアーキテクチャ
全(すべ)ての機能(きのう)が一(ひと)つのデプロイ単位(たんい)で構成(こうせい)されます。
+------------------------------------------+
| Monolith |
| +--------+ +--------+ +--------+ |
| | User | | Order | |Payment | |
| | Module | | Module | | Module | |
| +--------+ +--------+ +--------+ |
| +----------------------------------+ |
| | Shared Database | |
| +----------------------------------+ |
+------------------------------------------+
メリット:
- 開発(かいはつ)/デバッグ/デプロイがシンプル
- トランザクション管理(かんり)が容易(ようい)(ACID保証(ほしょう))
- IDEで全(ぜん)コード探索(たんさく)可能(かのう)
- ネットワーク遅延(ちえん)なし
デメリット:
- コードベース肥大化(ひだいか)でビルド/デプロイ時間(じかん)増加(ぞうか)
- 一(ひと)つのモジュール変更(へんこう)がシステム全体(ぜんたい)に影響(えいきょう)
- 技術(ぎじゅつ)スタック変更(へんこう)が困難(こんなん)
- チーム規模(きぼ)拡張(かくちょう)に限界(げんかい)
1.2 SOA(サービス指向アーキテクチャ)
2000年代(ねんだい)のエンタープライズ環境(かんきょう)で流行(りゅうこう)したアーキテクチャです。ESB(Enterprise Service Bus)を中心(ちゅうしん)にサービスを接続(せつぞく)します。
+--------+ +--------+ +--------+
| Service| | Service| | Service|
| A | | B | | C |
+---+----+ +---+----+ +---+----+
| | |
+---v-------------v-------------v---+
| Enterprise Service Bus |
| (SOAP, WSDL, XML, Routing) |
+-----------------------------------+
SOAはサービス再利用(さいりよう)を強調(きょうちょう)しましたが、ESBが過度(かど)なロジックを担当(たんとう)し、「Smart Pipes, Dumb Endpoints」アンチパターンが発生(はっせい)しました。
1.3 マイクロサービスアーキテクチャ
Netflix、Amazon、Uberが主導(しゅどう)した現代的(げんだいてき)な分散(ぶんさん)アーキテクチャです。
+--------+ +--------+ +--------+
| User | | Order | |Payment |
|Service | |Service | |Service |
| DB-A | | DB-B | | DB-C |
+---+----+ +---+----+ +---+----+
| | |
v v v
[REST/gRPC] [Kafka] [REST/gRPC]
核心(かくしん)原則(げんそく):
- ビジネス能力(のうりょく)中心(ちゅうしん)の分離(ぶんり)
- 「Dumb Pipes, Smart Endpoints」
- サービス別(べつ)独立(どくりつ)データストア
- 独立(どくりつ)したデプロイとスケーリング
- 障害(しょうがい)隔離(かくり)(Fault Isolation)
1.4 モジュラーモノリス — 2025年トレンド
MSAの複雑性(ふくざつせい)なしにモノリスの利点(りてん)を維持(いじ)しながら、モジュール間(かん)の境界(きょうかい)を明確(めいかく)にするアーキテクチャです。
+------------------------------------------+
| Modular Monolith |
| +----------+ +----------+ +--------+ |
| | User | | Order | |Payment | |
| | Module | | Module | | Module | |
| | [Schema] | | [Schema] | |[Schema]| |
| | [API] | | [API] | | [API] | |
| +----------+ +----------+ +--------+ |
| |Internal API| |Internal API| |
| +----------------------------------+ |
| | Shared Runtime (Single DB) | |
| +----------------------------------+ |
+------------------------------------------+
核心(かくしん)特性(とくせい):
- 単一(たんいつ)デプロイ単位(たんい)、しかしモジュール間(かん)境界(きょうかい)は厳格(げんかく)
- モジュール間(かん)通信(つうしん)は公開(こうかい)API(内部(ないぶ)インターフェース)を通(とお)してのみ
- 各(かく)モジュールは自身(じしん)のデータベーススキーマを所有(しょゆう)
- 必要(ひつよう)に応(おう)じて個別(こべつ)モジュールをサービスとして抽出(ちゅうしゅつ)可能(かのう)
1.5 アーキテクチャ進化タイムライン
| 年代 | アーキテクチャ | 主導企業 | 核心技術 |
|---|---|---|---|
| 2000s | SOA | IBM, Oracle | ESB, SOAP, WSDL |
| 2010s前半 | MSA台頭 | Netflix, Amazon | REST, Docker |
| 2015-2020 | MSA全盛期 | Uber, Spotify | K8s, Istio, gRPC |
| 2020-2023 | MSA疲労感 | 多数のスタートアップ | 複雑性爆発 |
| 2024-2025 | モジュラーモノリス復活 | Shopify, Basecamp | Vertical Slices |
2. MSAが過剰な場合:反省と教訓
2.1 DHHのMajestic Monolith
Ruby on Rails創設者(そうせつしゃ)のDavid Heinemeier Hanssonは「マイクロサービスはほとんどのチームにとって不要(ふよう)な複雑性(ふくざつせい)」と強(つよ)く主張(しゅちょう)しています。BasecampとHEYは数百万(すうひゃくまん)ユーザーを単一(たんいつ)モノリスでサービスしています。
核心(かくしん)論点(ろんてん):
- ほとんどのWebアプリケーションは単一(たんいつ)サーバーで十分(じゅうぶん)
- MSAの運用(うんよう)複雑性(ふくざつせい)はチームの速度(そくど)を低下(ていか)させる
- マイクロサービスは100名(めい)以上(いじょう)のエンジニアリング組織(そしき)でのみ意味(いみ)がある
2.2 Amazon Prime Videoの事例
2023年(ねん)、Amazon Prime Videoチームはマイクロサービスアーキテクチャからモノリスに移行(いこう)してコストを90%削減(さくげん)したと発表(はっぴょう)しました。
元(もと)のMSAアーキテクチャの問題(もんだい):
- AWS Step Functionsによるオーケストレーション → 状態(じょうたい)遷移(せんい)コスト過大(かだい)
- サービス間(かん)データ転送(てんそう)にS3使用(しよう) → I/Oコスト爆発(ばくはつ)
- マイクロサービス間(かん)のネットワーク遅延(ちえん)でリアルタイム処理(しょり)不可能(ふかのう)
モノリス移行後(いこうご):
- インフラコスト90%削減(さくげん)
- アーキテクチャ簡素化(かんそか)でデバッグ効率(こうりつ)向上(こうじょう)
- 同(おな)じプロセス内(ない)の関数(かんすう)呼(よ)び出(だ)しで遅延(ちえん)時間(じかん)最小化(さいしょうか)
2.3 SegmentのMSAからモノリス回帰
Segmentは140個(こ)以上(いじょう)のマイクロサービスを運用(うんよう)した後(のち)、再(ふたた)びモノリスに統合(とうごう)しました。
問題点(もんだいてん):
- 140個(こ)のサービスの同一(どういつ)コード変更(へんこう)を同期(どうき)するのが困難(こんなん)
- サービス別(べつ)独立(どくりつ)デプロイがかえって統合(とうごう)テストを不可能(ふかのう)にした
- インフラコストがビジネス成長率(せいちょうりつ)を超過(ちょうか)
教訓(きょうくん): サービスを分離(ぶんり)する前(まえ)に「このサービスは独立(どくりつ)してデプロイ・スケーリングする必要(ひつよう)があるか?」を必(かなら)ず検証(けんしょう)すべきです。
3. モジュラーモノリス深堀り
3.1 Vertical Sliceアーキテクチャ
従来(じゅうらい)の階層型(かいそうがた)(Layered)アーキテクチャの代(か)わりに、機能(きのう)単位(たんい)(Feature)でコードを垂直(すいちょく)分割(ぶんかつ)します。
従来の階層型:
Controllers/ -> Services/ -> Repositories/ -> Models/
Vertical Slice:
Features/
CreateOrder/
CreateOrderCommand.cs
CreateOrderHandler.cs
CreateOrderValidator.cs
CreateOrderEndpoint.cs
GetOrderById/
GetOrderByIdQuery.cs
GetOrderByIdHandler.cs
GetOrderByIdEndpoint.cs
// Vertical Sliceの例 - MediatRパターン
public record CreateOrderCommand(
string CustomerId,
List<OrderItem> Items
) : IRequest<OrderResult>;
public class CreateOrderHandler
: IRequestHandler<CreateOrderCommand, OrderResult>
{
private readonly OrderDbContext _db;
private readonly IEventBus _eventBus;
public CreateOrderHandler(OrderDbContext db, IEventBus eventBus)
{
_db = db;
_eventBus = eventBus;
}
public async Task<OrderResult> Handle(
CreateOrderCommand cmd,
CancellationToken ct)
{
var order = Order.Create(cmd.CustomerId, cmd.Items);
_db.Orders.Add(order);
await _db.SaveChangesAsync(ct);
await _eventBus.Publish(new OrderCreatedEvent(order.Id));
return new OrderResult(order.Id, order.TotalAmount);
}
}
3.2 モジュール境界の設定
// モジュール間通信は必ず公開インターフェースを通じて
// order-module/src/main/java/com/app/order/api/
public interface OrderModuleApi {
OrderDto getOrder(String orderId);
OrderDto createOrder(CreateOrderRequest request);
void cancelOrder(String orderId);
}
// order-module/src/main/java/com/app/order/internal/
// このパッケージのクラスは外部モジュールからアクセス不可
class OrderServiceImpl implements OrderModuleApi {
private final OrderRepository repository;
private final PaymentModuleApi paymentModule;
@Override
public OrderDto createOrder(CreateOrderRequest request) {
Order order = Order.create(request);
repository.save(order);
paymentModule.initiatePayment(order.getId(), order.getTotal());
return OrderDto.from(order);
}
}
3.3 Spring Modulith実践
Spring ModulithはモジュラーモノリスのためのSpring公式(こうしき)フレームワークです。
// モジュール構造
com.example.app/
order/ // Orderモジュール(ルートパッケージ)
OrderService.java
Order.java
internal/ // 外部アクセス不可
OrderRepository.java
OrderEventHandler.java
payment/ // Paymentモジュール
PaymentService.java
internal/
PaymentProcessor.java
inventory/ // Inventoryモジュール
InventoryService.java
// Spring Modulithイベントベースのモジュール間通信
@Service
@RequiredArgsConstructor
public class OrderService {
private final ApplicationEventPublisher events;
@Transactional
public Order createOrder(CreateOrderRequest request) {
var order = new Order(request.customerId(), request.items());
orderRepo.save(order);
// イベント発行 — Paymentモジュールが非同期で受信
events.publishEvent(new OrderCreated(order.getId(), order.getTotal()));
return order;
}
}
// Paymentモジュールのイベントハンドラー
@Service
public class PaymentEventHandler {
@ApplicationModuleListener
public void onOrderCreated(OrderCreated event) {
paymentService.processPayment(event.orderId(), event.amount());
}
}
// モジュール構造検証テスト
@Test
void verifyModularStructure() {
ApplicationModules modules = ApplicationModules.of(Application.class);
modules.verify(); // 循環依存性、パッケージアクセス違反を検証
}
4. DDD基盤のサービス分解戦略
4.1 Bounded Contextの識別
Domain-Driven Designにおいて、バウンデッドコンテキストはマイクロサービス分離(ぶんり)の核心(かくしん)基準(きじゅん)です。
+----------------+ +------------------+ +----------------+
| Order BC | | Payment BC | | Inventory BC |
| | | | | |
| - Order | | - Payment | | - Product |
| - OrderLine | | - Transaction | | - Stock |
| - Customer(ref)| | - Order(ref) | | - Warehouse |
+-------+--------+ +--------+---------+ +-------+--------+
| | |
+----------- Events ---------------------+------+
Context Mappingパターン:
| パターン | 説明 | 使用場面 |
|---|---|---|
| Shared Kernel | 2つのコンテキストがコード/モデル共有 | 密接なチーム間 |
| Customer-Supplier | アップストリームがダウンストリームにAPI提供 | チーム間依存関係 |
| Conformist | ダウンストリームがアップストリームモデルをそのまま受容 | 外部サービス統合 |
| Anti-Corruption Layer | 翻訳レイヤーで外部モデルを遮断 | レガシー統合 |
| Open Host Service | 標準プロトコルで公開API提供 | 多数のコンシューマー |
| Published Language | 共有スキーマ(JSON Schema, Protobuf) | イベント駆動 |
4.2 Event Storming
Event Stormingはビジネス専門家(せんもんか)と開発者(かいはつしゃ)が一緒(いっしょ)にドメインを探索(たんさく)するワークショップ技法(ぎほう)です。
[オレンジ] Domain Event: 「注文が作成された」
[青] Command: 「注文作成」
[黄] Aggregate: 「Order」
[ピンク] External System: 「決済ゲートウェイ」
[紫] Policy: 「注文作成時に在庫を減らす」
[赤] Hot Spot: 「決済失敗時の在庫復旧は?」
タイムライン:
注文作成 -> 在庫確認 -> 決済要求 -> 決済完了 -> 出荷開始
-> 決済失敗 -> 在庫復旧 -> 注文キャンセル
5. 通信パターン:同期 vs 非同期
5.1 同期通信の比較
| 基準 | REST (HTTP/JSON) | gRPC (HTTP/2, Protobuf) | GraphQL |
|---|---|---|---|
| プロトコル | HTTP/1.1 or 2 | HTTP/2 | HTTP/1.1 or 2 |
| シリアライズ | JSON(テキスト) | Protobuf(バイナリ) | JSON(テキスト) |
| パフォーマンス | 普通 | 高い(10倍速い) | 普通 |
| ストリーミング | 制限的 | 双方向 | Subscription |
| コード生成 | OpenAPI(任意) | 必須(protoファイル) | 任意 |
| ブラウザ対応 | 完全 | gRPC-Web必要 | 完全 |
| 最適な用途 | 外部API | 内部サービス間 | BFF、モバイル |
5.2 gRPCサービス定義
// order_service.proto
syntax = "proto3";
package order;
service OrderService {
// Unary RPC
rpc CreateOrder(CreateOrderRequest) returns (OrderResponse);
rpc GetOrder(GetOrderRequest) returns (OrderResponse);
// Server Streaming
rpc WatchOrderStatus(GetOrderRequest) returns (stream OrderStatusUpdate);
// Bidirectional Streaming
rpc ChatSupport(stream ChatMessage) returns (stream ChatMessage);
}
message CreateOrderRequest {
string customer_id = 1;
repeated OrderItem items = 2;
ShippingAddress shipping_address = 3;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
double unit_price = 3;
}
message OrderResponse {
string order_id = 1;
OrderStatus status = 2;
double total_amount = 3;
google.protobuf.Timestamp created_at = 4;
}
enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0;
ORDER_STATUS_PENDING = 1;
ORDER_STATUS_CONFIRMED = 2;
ORDER_STATUS_SHIPPED = 3;
ORDER_STATUS_DELIVERED = 4;
ORDER_STATUS_CANCELLED = 5;
}
5.3 非同期通信の比較
| 基準 | Apache Kafka | RabbitMQ | NATS |
|---|---|---|---|
| モデル | ログベースストリーム | メッセージキュー | Pub/Sub + キュー |
| スループット | 非常に高い(数百万TPS) | 高い(数万TPS) | 非常に高い |
| メッセージ保持 | 永続保持可能 | 消費後削除 | デフォルト非保持 |
| 順序保証 | パーティション内保証 | キュー内保証 | 非保証 |
| 再処理 | オフセットリセットで可能 | 不可能(DLQ活用) | JetStreamで可能 |
| 最適な用途 | イベントソーシング、大量処理 | タスクキュー、RPC | 軽量メッセージング |
5.4 Kafkaイベント駆動通信
// イベント定義
public record OrderCreatedEvent(
String eventId,
String orderId,
String customerId,
BigDecimal totalAmount,
List<OrderItemDto> items,
Instant occurredAt
) {}
// Producer (Order Service)
@Service
@RequiredArgsConstructor
public class OrderEventPublisher {
private final KafkaTemplate<String, OrderCreatedEvent> kafkaTemplate;
public void publishOrderCreated(Order order) {
var event = new OrderCreatedEvent(
UUID.randomUUID().toString(),
order.getId(),
order.getCustomerId(),
order.getTotalAmount(),
order.getItems().stream().map(OrderItemDto::from).toList(),
Instant.now()
);
kafkaTemplate.send("order-events", order.getId(), event)
.whenComplete((result, ex) -> {
if (ex != null) {
log.error("Failed to publish event: {}", ex.getMessage());
} else {
log.info("Event published to partition {} offset {}",
result.getRecordMetadata().partition(),
result.getRecordMetadata().offset());
}
});
}
}
// Consumer (Payment Service)
@Service
public class PaymentEventConsumer {
@KafkaListener(
topics = "order-events",
groupId = "payment-service",
containerFactory = "kafkaListenerContainerFactory"
)
public void handleOrderCreated(
@Payload OrderCreatedEvent event,
@Header(KafkaHeaders.RECEIVED_PARTITION) int partition,
@Header(KafkaHeaders.OFFSET) long offset
) {
log.info("Received OrderCreated: orderId={}, partition={}, offset={}",
event.orderId(), partition, offset);
paymentService.processPayment(event.orderId(), event.totalAmount());
}
}
6. Service Mesh比較と実践
6.1 Service Meshアーキテクチャ
Service Meshはサービス間(かん)通信(つうしん)をインフラレベルで管理(かんり)します。サイドカープロキシが全(すべ)てのネットワークトラフィックをインターセプトして処理(しょり)します。
+---------------------------------------------+
| Service A Pod |
| +-------------+ +------------------+ |
| | Application | --> | Envoy Sidecar | |
| | Container | <-- | Proxy | |
| +-------------+ +------------------+ |
+---------------------------------------------+
| mTLS |
+---------------------------------------------+
| Service B Pod |
| +------------------+ +-------------+ |
| | Envoy Sidecar | --> | Application | |
| | Proxy | <-- | Container | |
| +------------------+ +-------------+ |
+---------------------------------------------+
|
+---------------------------------------------+
| Control Plane (Istiod) |
| - Certificate Authority (mTLS) |
| - Configuration Distribution |
| - Service Discovery |
+---------------------------------------------+
6.2 Istio vs Linkerd vs Consul Connect
| 機能 | Istio | Linkerd | Consul Connect |
|---|---|---|---|
| データプレーン | Envoy | linkerd2-proxy (Rust) | Envoy / built-in |
| リソース使用量 | 高い | 低い | 中程度 |
| 学習曲線 | 急勾配 | 緩やか | 中程度 |
| mTLS | 自動 | 自動 | 自動 |
| トラフィック管理 | 非常に豊富 | 基本的 | 基本的 |
| オブザーバビリティ | Kiali, Jaeger | Viz Dashboard | Consul UI |
| マルチクラスター | 対応 | 対応 | 強力に対応 |
| WASM拡張 | 対応 | 非対応 | 非対応 |
| 推奨用途 | 大規模/複雑な環境 | 軽量/シンプルな環境 | HashiCorpスタック |
6.3 Istioトラフィック管理
# VirtualService - カナリーデプロイ
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: order-service
subset: canary
weight: 100
- route:
- destination:
host: order-service
subset: stable
weight: 90
- destination:
host: order-service
subset: canary
weight: 10
---
# DestinationRule - サブセット定義
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
h2UpgradePolicy: UPGRADE
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: stable
labels:
version: v1
- name: canary
labels:
version: v2
7. 分散トランザクション:Sagaパターン
7.1 Choreography vs Orchestration
分散(ぶんさん)環境(かんきょう)では2PC(Two-Phase Commit)はパフォーマンスと可用性(かようせい)の問題(もんだい)で非実用的(ひじつようてき)です。Sagaパターンはローカルトランザクションのシーケンスで分散(ぶんさん)トランザクションを管理(かんり)します。
Choreography(イベントベース):
Order Service Payment Service Inventory Service
| | |
| OrderCreated | |
|--------------------->| |
| | PaymentProcessed |
| |--------------------->|
| | | InventoryReserved
| | |----->
| | |
| [失敗時の補償トランザクション] |
| | |
| | PaymentFailed |
| |--------------------->|
| | | InventoryReleased
| OrderCancelled | |
|<---------------------| |
Orchestration(中央コーディネーター):
Order Saga Orchestrator
|
+--------------+--------------+
| | |
v v v
Order Service Payment Service Inventory Service
create() processPayment() reserveStock()
cancel() refund() releaseStock()
7.2 TemporalベースのSaga Orchestration
// Temporal Workflow定義
func OrderSagaWorkflow(ctx workflow.Context, input OrderInput) (OrderResult, error) {
logger := workflow.GetLogger(ctx)
var result OrderResult
activityOpts := workflow.ActivityOptions{
StartToCloseTimeout: 30 * time.Second,
RetryPolicy: &temporal.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumInterval: time.Minute,
MaximumAttempts: 3,
},
}
ctx = workflow.WithActivityOptions(ctx, activityOpts)
// Step 1: 注文作成
var orderID string
err := workflow.ExecuteActivity(ctx, CreateOrderActivity, input).Get(ctx, &orderID)
if err != nil {
return result, fmt.Errorf("create order failed: %w", err)
}
// Step 2: 決済処理
var paymentID string
err = workflow.ExecuteActivity(ctx, ProcessPaymentActivity, orderID, input.Amount).Get(ctx, &paymentID)
if err != nil {
// 補償トランザクション: 注文キャンセル
logger.Info("Payment failed, cancelling order", "orderID", orderID)
_ = workflow.ExecuteActivity(ctx, CancelOrderActivity, orderID).Get(ctx, nil)
return result, fmt.Errorf("payment failed: %w", err)
}
// Step 3: 在庫確保
err = workflow.ExecuteActivity(ctx, ReserveInventoryActivity, orderID, input.Items).Get(ctx, nil)
if err != nil {
// 補償トランザクション: 返金 + 注文キャンセル
logger.Info("Inventory reservation failed, compensating", "orderID", orderID)
_ = workflow.ExecuteActivity(ctx, RefundPaymentActivity, paymentID).Get(ctx, nil)
_ = workflow.ExecuteActivity(ctx, CancelOrderActivity, orderID).Get(ctx, nil)
return result, fmt.Errorf("inventory reservation failed: %w", err)
}
result = OrderResult{
OrderID: orderID,
PaymentID: paymentID,
Status: "CONFIRMED",
}
return result, nil
}
7.3 Transactional Outboxパターン
イベント発行(はっこう)の原子性(げんしせい)を保証(ほしょう)するために、イベントをDBテーブルに先(さき)に保存(ほぞん)した後(あと)、別(べつ)のプロセスが発行(はっこう)します。
-- Outboxテーブル
CREATE TABLE outbox_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
aggregate_type VARCHAR(255) NOT NULL,
aggregate_id VARCHAR(255) NOT NULL,
event_type VARCHAR(255) NOT NULL,
payload JSONB NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
published_at TIMESTAMP NULL
);
// Outboxパターン実装
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepo;
private final OutboxRepository outboxRepo;
@Transactional // 注文保存とイベント保存が一つのトランザクション
public Order createOrder(CreateOrderRequest request) {
Order order = Order.create(request);
orderRepo.save(order);
OutboxEvent event = OutboxEvent.builder()
.aggregateType("Order")
.aggregateId(order.getId())
.eventType("OrderCreated")
.payload(toJson(new OrderCreatedEvent(order)))
.build();
outboxRepo.save(event);
return order;
}
}
8. オブザーバビリティ:OpenTelemetryスタック
8.1 オブザーバビリティの3要素
+---------------------------------------------------+
| Observability |
| |
| +--------+ +---------+ +---------+ |
| | Logs | | Metrics | | Traces | |
| | (What) | | (How) | | (Where) | |
| +--------+ +---------+ +---------+ |
| |
| 「エラー発生」「遅延増加」 「どこで遅い?」 |
+---------------------------------------------------+
8.2 OpenTelemetry設定
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
send_batch_size: 1024
timeout: 5s
exporters:
prometheusremotewrite:
endpoint: "http://prometheus:9090/api/v1/write"
otlp/jaeger:
endpoint: "jaeger:4317"
tls:
insecure: true
loki:
endpoint: "http://loki:3100/loki/api/v1/push"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheusremotewrite]
logs:
receivers: [otlp]
processors: [batch]
exporters: [loki]
8.3 分散トレーシング実装
// Spring Boot + OpenTelemetry自動計装
@Service
public class OrderService {
private final Tracer tracer;
public Order createOrder(CreateOrderRequest request) {
Span span = tracer.spanBuilder("createOrder")
.setAttribute("order.customer_id", request.getCustomerId())
.setAttribute("order.item_count", request.getItems().size())
.startSpan();
try (Scope scope = span.makeCurrent()) {
Order order = processOrder(request);
span.setAttribute("order.id", order.getId());
span.setStatus(StatusCode.OK);
return order;
} catch (Exception e) {
span.setStatus(StatusCode.ERROR, e.getMessage());
span.recordException(e);
throw e;
} finally {
span.end();
}
}
}
8.4 主要メトリクス(RED Method)
RED Method(サービスレベルメトリクス):
- Rate: 秒あたりのリクエスト数
- Errors: エラー率
- Duration: レイテンシパーセンタイル
USE Method(インフラレベルメトリクス):
- Utilization: CPU/メモリ使用率
- Saturation: キュー深度、待機スレッド数
- Errors: システムエラー数
9. API Gatewayパターン
9.1 API Gatewayの役割
Client (Web/Mobile/Partner)
|
v
+---------------------+
| API Gateway |
| - ルーティング |
| - 認証/認可 |
| - Rate Limiting |
| - ロードバランシング |
| - キャッシング |
| - リクエスト変換 |
| - Circuit Breaker |
+---------------------+
| | |
v v v
User Order Payment
Service Service Service
9.2 主要API Gateway比較
| 機能 | Kong | AWS API Gateway | NGINX | Envoy |
|---|---|---|---|---|
| タイプ | OSS + Enterprise | マネージド | OSS | OSS |
| プラグイン | 豊富(Lua) | Lambda統合 | モジュール | Filter Chain |
| パフォーマンス | 高い | 中程度 | 非常に高い | 非常に高い |
| K8s統合 | Ingress Controller | - | Ingress Controller | Gateway API |
| gRPC | 対応 | 対応 | 制限的 | ネイティブ |
| コスト | 自己運用 | リクエスト課金 | 自己運用 | 自己運用 |
10. デプロイ戦略
10.1 デプロイ戦略比較
| 戦略 | ダウンタイム | ロールバック速度 | リソースコスト | リスク |
|---|---|---|---|---|
| Rolling Update | なし | 遅い | 低い | 中程度 |
| Blue-Green | なし | 即時 | 2倍 | 低い |
| Canary | なし | 速い | やや追加 | 非常に低い |
| A/B Testing | なし | 速い | やや追加 | 低い |
10.2 Argo Rolloutsによるカナリーデプロイ
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: order-service
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 5
- pause:
duration: 5m
- analysis:
templates:
- templateName: success-rate
- setWeight: 25
- pause:
duration: 10m
- setWeight: 50
- pause:
duration: 10m
- setWeight: 100
canaryService: order-service-canary
stableService: order-service-stable
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: registry.example.com/order-service:v2.1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
11. マイグレーション戦略:モノリスからMSAへ
11.1 Strangler Figパターン
既存(きぞん)システムを包(つつ)みながら、段階的(だんかいてき)に新(あたら)しいシステムにトラフィックを移行(いこう)します。
Phase 1: プロキシ導入
+--------+ +-------+ +-----------+
| Client | --> | Proxy | --> | Monolith |
+--------+ +-------+ +-----------+
Phase 2: 一部機能の抽出
+--------+ +-------+---> +-----------+
| Client | --> | Proxy | | Monolith |
+--------+ +---+---+ +-----------+
|
+--------> +-----------+
| New User |
| Service |
+-----------+
Phase 3: 段階的な移行完了
+--------+ +-------+---> +-----------+
| Client | --> | Proxy | | Monolith | (縮小)
+--------+ +---+---+ +-----------+
|
+--------> +-----------+
| | User Svc |
+--------> +-----------+
| | Order Svc |
+--------> +-----------+
| Pay Svc |
+-----------+
11.2 Branch by Abstraction
// Step 1: 抽象化レイヤー導入
public interface NotificationService {
void sendEmail(String to, String subject, String body);
void sendSms(String to, String message);
}
// Step 2: 既存実装のラッピング
public class LegacyNotificationService implements NotificationService {
private final MonolithNotificationModule legacy;
public void sendEmail(String to, String subject, String body) {
legacy.email(to, subject, body);
}
}
// Step 3: 新実装の開発
public class NewNotificationService implements NotificationService {
private final EmailClient emailClient;
private final SmsGateway smsGateway;
public void sendEmail(String to, String subject, String body) {
emailClient.send(to, subject, body);
}
}
// Step 4: Feature Flagで切り替え
@Service
public class NotificationServiceRouter implements NotificationService {
private final LegacyNotificationService legacy;
private final NewNotificationService modern;
private final FeatureFlags flags;
public void sendEmail(String to, String subject, String body) {
if (flags.isEnabled("use-new-notification-service")) {
modern.sendEmail(to, subject, body);
} else {
legacy.sendEmail(to, subject, body);
}
}
}
12. アンチパターン:これだけは避けよう
12.1 分散モノリス
MSAの形(かたち)を持(も)ちながら、モノリスの全(すべ)てのデメリットと分散(ぶんさん)システムの複雑性(ふくざつせい)を併(あわ)せ持(も)つ最悪(さいあく)の状態(じょうたい)です。
悪い例:
Service A --sync--> Service B --sync--> Service C --sync--> Service D
| | |
+------------ 共有データベース -----------+
良い例:
Service A --event--> Service B --event--> Service C
[DB-A] [DB-B] [DB-C]
12.2 ナノサービス
サービスが小(ちい)さすぎて独立(どくりつ)して意味(いみ)がなく、運用(うんよう)オーバーヘッドだけが増加(ぞうか)します。
悪い例:
- User Profile Service
- User Address Service
- User Preference Service
- User Avatar Service
- User Notification Settings Service
-> 5サービス + 5DB + 5CI/CD + 5モニタリング
良い例:
- User Service(Profile, Address, Preference, Avatar統合)
-> 1サービス、内部モジュールで分離
12.3 同期呼び出し地獄
問題:
Client -> API GW -> Auth -> User -> Order -> Inventory -> Payment
全体遅延 = 各サービス遅延の合計
全体可用性 = 各サービス可用性の積
(99.9%)^6 = 99.4%(年間52時間のダウンタイム!)
解決策:
1. 非同期メッセージングに切り替え
2. CQRSで読み取りを最適化
3. 必須パスのみ同期、残りはイベント駆動
13. 意思決定フレームワーク
13.1 チーム規模別推奨アーキテクチャ
開発者1-5名:
-> モノリス(Simple is best)
開発者5-20名:
-> モジュラーモノリス(モジュール境界設定)
開発者20-50名:
-> モジュラーモノリス + コアサービス2-3個分離
開発者50-200名:
-> MSA(チーム単位のサービスオーナーシップ)
開発者200名+:
-> MSA + Platform Engineering
13.2 決定マトリクス
| 基準 | モノリス | モジュラーモノリス | MSA |
|---|---|---|---|
| チーム規模 | 1-10名 | 5-50名 | 20名+ |
| デプロイ頻度 | 週1回以下 | 週数回 | 日数十回 |
| スケーリング | 均一 | 部分的 | サービス別独立 |
| 技術多様性 | 単一スタック | 単一スタック | ポリグロット |
| 運用能力 | 低くてもOK | 中程度 | 高い必要あり |
| 初期速度 | 速い | 速い | 遅い |
| 障害隔離 | 不可 | 制限的 | 完全隔離 |
14. 面接対策:マイクロサービス核心質問20選
Q1. マイクロサービスとモノリスの違いを説明してください。
モノリスは全(すべ)ての機能(きのう)が一(ひと)つのデプロイ単位(たんい)で構成(こうせい)され、マイクロサービスはビジネス能力(のうりょく)単位(たんい)で独立(どくりつ)してデプロイ・スケーリング可能(かのう)な小(ちい)さなサービス群(ぐん)で構成(こうせい)されます。モノリスはトランザクション管理(かんり)が簡単(かんたん)ですがスケーラビリティに限界(げんかい)があり、MSAは独立(どくりつ)デプロイ・スケーリングが可能(かのう)ですが分散(ぶんさん)システムの複雑性(ふくざつせい)が増加(ぞうか)します。
Q2. サービス分解の基準は何ですか?
DDDのBounded Contextが最(もっと)も重要(じゅうよう)な基準(きじゅん)です。ドメインモデルが一貫性(いっかんせい)を維持(いじ)する境界(きょうかい)を識別(しきべつ)し、その境界(きょうかい)に沿(そ)ってサービスを分離(ぶんり)します。さらに独立(どくりつ)デプロイの必要性(ひつようせい)、スケーリング要件(ようけん)の差異(さい)、チームオーナーシップ、技術(ぎじゅつ)スタックの違(ちが)いを考慮(こうりょ)します。
Q3. SagaパターンのChoreographyとOrchestrationの違いを説明してください。
Choreographyは各(かく)サービスがイベントを発行(はっこう)・購読(こうどく)して自律的(じりつてき)に進行(しんこう)します。中央(ちゅうおう)コーディネーターがなく疎結合(そけつごう)ですが、フロー追跡(ついせき)が困難(こんなん)です。Orchestrationは中央(ちゅうおう)コーディネーター(Temporal、Camunda等(とう))が全体(ぜんたい)フローを制御(せいぎょ)します。ビジネスロジックが一箇所(いっかしょ)に集(あつ)まり可視性(かしせい)が良(よ)いですが、単一障害点(たんいつしょうがいてん)になりえます。
Q4. Service Meshが必要な理由は何ですか?
サービス数(すう)が増加(ぞうか)すると、サービス間(かん)通信(つうしん)の共通(きょうつう)関心事(かんしんじ)(mTLS、ロードバランシング、サーキットブレーカー、リトライ、オブザーバビリティ)を各(かく)サービスに実装(じっそう)するのが困難(こんなん)になります。Service Meshはこれをインフラレベル(サイドカープロキシ)で透過的(とうかてき)に処理(しょり)し、アプリケーションコードをクリーンに保(たも)ちます。
Q5. 分散モノリスとは何か、どう防止しますか?
分散(ぶんさん)モノリスはMSAの形態(けいたい)を持(も)ちながら、サービス間(かん)の強(つよ)い結合(けつごう)により独立(どくりつ)デプロイが不可能(ふかのう)な状態(じょうたい)です。防止(ぼうし)するには非同期(ひどうき)通信(つうしん)優先(ゆうせん)、サービス別(べつ)独立(どくりつ)データベース、APIバージョニング、Consumer-Driven Contract Testingを適用(てきよう)します。
Q6. gRPCがRESTより有利な場合はいつですか?
内部(ないぶ)サービス間(かん)通信(つうしん)でgRPCが有利(ゆうり)です。ProtobufバイナリシリアライゼーションはJSON比(ひ)で10倍(ばい)以上(いじょう)速(はや)く、HTTP/2ベースのマルチプレクシングと双方向(そうほうこう)ストリーミングをサポートします。コード生成(せいせい)で型安全(かたあんぜん)なAPIを保証(ほしょう)します。一方(いっぽう)、ブラウザ直接(ちょくせつ)呼(よ)び出(だ)しが必要(ひつよう)な外部(がいぶ)APIにはRESTが適(てき)しています。
Q7. Transactional Outboxパターンを説明してください。
イベント発行(はっこう)の原子性(げんしせい)を保証(ほしょう)するパターンです。ビジネスデータ変更(へんこう)とイベントを同(おな)じDBトランザクションで保存(ほぞん)(outboxテーブル)し、別(べつ)プロセス(Debezium CDCまたはポーラー)がoutboxテーブルのイベントをメッセージブローカーに送信(そうしん)します。DBトランザクションがロールバックされればイベントも一緒(いっしょ)にロールバックされます。
Q8. CQRSはいつ使用しますか?
Command(書(か)き込(こ)み)とQuery(読(よ)み取(と)り)の要件(ようけん)が大(おお)きく異(こと)なる時(とき)に使用(しよう)します。例(たと)えば、書(か)き込(こ)みは正規化(せいきか)されたRDBMS、読(よ)み取(と)りは非正規化(ひせいきか)されたNoSQL/Elasticsearchで最適化(さいてきか)できます。Event Sourcingと共(とも)に使(つか)うと強力(きょうりょく)ですが、複雑性(ふくざつせい)が増(ま)すため、ホットスポット機能(きのう)にのみ適用(てきよう)するのが良(よ)いです。
Q9. カナリーデプロイとBlue-Greenデプロイの違いを説明してください。
Blue-Greenは2つの同一(どういつ)環境(かんきょう)を維持(いじ)しトラフィックを一度(いちど)に切(き)り替(か)えます。即時(そくじ)ロールバック可能(かのう)ですがリソースが2倍(ばい)必要(ひつよう)です。カナリーは少数(しょうすう)のトラフィック(5-10%)のみ新(あたら)しいバージョンに送(おく)り、メトリクスを確認(かくにん)しながら段階的(だんかいてき)に比率(ひりつ)を上(あ)げます。リスクは低(ひく)いですが完了(かんりょう)に時間(じかん)がかかります。
Q10. OpenTelemetryの役割を説明してください。
OpenTelemetryは分散(ぶんさん)システムのオブザーバビリティのための統一(とういつ)標準(ひょうじゅん)です。Traces、Metrics、Logsを単一(たんいつ)SDKで収集(しゅうしゅう)し、ベンダー中立(ちゅうりつ)のOTLPプロトコルで様々(さまざま)なバックエンド(Jaeger、Prometheus、Grafana)に送信(そうしん)します。
Q11. モジュラーモノリスが2025年に注目される理由は?
MSAの運用(うんよう)複雑性(ふくざつせい)を経験(けいけん)した多(おお)くのチームが「必要(ひつよう)だったのは適切(てきせつ)なモジュール境界(きょうかい)であり、別々(べつべつ)のサービスではなかった」と気(き)づきました。モジュラーモノリスはMSAのモジュール性(せい)を維持(いじ)しながら運用(うんよう)複雑性(ふくざつせい)を大幅(おおはば)に削減(さくげん)し、必要(ひつよう)に応(おう)じてサービスを抽出(ちゅうしゅつ)できる柔軟性(じゅうなんせい)を提供(ていきょう)します。
Q12. Strangler Figパターンを説明してください。
レガシーシステムを段階的(だんかいてき)に新(あたら)しいシステムに移行(いこう)するマイグレーションパターンです。プロキシ(API Gateway)を前(まえ)に配置(はいち)し、新(あたら)しい機能(きのう)は新(あたら)しいサービスとして実装(じっそう)し、既存(きぞん)の機能(きのう)も段階的(だんかいてき)に移行(いこう)します。ビッグバンマイグレーションのリスクを軽減(けいげん)します。
Q13. API GatewayとService Meshの違いは何ですか?
API Gatewayは外部(がいぶ)トラフィック(North-South)を処理(しょり)し、認証(にんしょう)、Rate Limiting、API変換(へんかん)を担当(たんとう)します。Service Meshは内部(ないぶ)サービス間(かん)トラフィック(East-West)を管理(かんり)し、mTLS、サーキットブレーカー、ロードバランシング、オブザーバビリティを提供(ていきょう)します。両方(りょうほう)必要(ひつよう)な場合(ばあい)があり、相互(そうご)補完的(ほかんてき)です。
Q14. 冪等性がマイクロサービスで重要な理由は?
ネットワーク障害(しょうがい)によるリトライやメッセージ重複(じゅうふく)が発生(はっせい)しうる分散(ぶんさん)環境(かんきょう)では、同(おな)じリクエストを複数回(ふくすうかい)処理(しょり)しても結果(けっか)が同一(どういつ)でなければなりません。冪等性(べきとうせい)キーの使用(しよう)やデータベースのユニーク制約(せいやく)で実装(じっそう)します。
Q15. Event Sourcingとは何か、いつ使用しますか?
状態(じょうたい)変更(へんこう)をイベントのシーケンスとして保存(ほぞん)するパターンです。現在(げんざい)の状態(じょうたい)はイベントをリプレイして導出(どうしゅつ)します。監査(かんさ)ログが必須(ひっす)な金融(きんゆう)システム、タイムトラベル(特定(とくてい)時点(じてん)の状態(じょうたい)照会(しょうかい))が必要(ひつよう)な場合(ばあい)、CQRSと共(とも)に使用(しよう)すると効果的(こうかてき)です。複雑性(ふくざつせい)が高(たか)いため、全(すべ)てのサービスへの適用(てきよう)は非推奨(ひすいしょう)です。
Q16. Circuit Breakerパターンを説明してください。
外部(がいぶ)サービス呼(よ)び出(だ)し失敗(しっぱい)が閾値(しきいち)を超(こ)えると回路(かいろ)を開(ひら)いて即座(そくざ)に失敗(しっぱい)を返(かえ)すパターンです。Closed(正常(せいじょう))- Open(遮断(しゃだん))- Half-Open(試験的(しけんてき)許可(きょか))の3状態(じょうたい)を循環(じゅんかん)します。障害(しょうがい)伝播(でんぱ)を防止(ぼうし)しシステム全体(ぜんたい)の安定性(あんていせい)を維持(いじ)します。
Q17. Consumer-Driven Contract Testingとは何ですか?
APIコンシューマーが期待(きたい)する契約(けいやく)(Contract)を定義(ていぎ)し、プロバイダーがこの契約(けいやく)を充足(じゅうそく)しているかテストします。Pactフレームワークが代表的(だいひょうてき)です。MSAでの統合(とうごう)テストの困難(こんなん)さを解決(かいけつ)し、API変更(へんこう)がコンシューマーを壊(こわ)さないことを保証(ほしょう)します。
Q18. データ一貫性維持の戦略は何ですか?
強(つよ)い一貫性(いっかんせい)が必要(ひつよう)なら同期(どうき)呼(よ)び出(だ)し + 分散(ぶんさん)トランザクション(Saga)、最終的(さいしゅうてき)一貫性(いっかんせい)が許容(きょよう)されるならイベントベースの非同期(ひどうき)通信(つうしん)を使用(しよう)します。Outboxパターンでイベント発行(はっこう)の原子性(げんしせい)を保証(ほしょう)し、CDC(Change Data Capture)でDB変更(へんこう)をイベントとしてキャプチャできます。
Q19. マイクロサービスでのログ戦略はどう設計しますか?
構造化(こうぞうか)ログ(JSON)、相関(そうかん)ID(Correlation ID)によるリクエスト追跡(ついせき)、中央集権的(ちゅうおうしゅうけんてき)なログ収集(しゅうしゅう)(ELK、Loki)、ログレベルの動的(どうてき)変更(へんこう)機能(きのう)が核心(かくしん)です。OpenTelemetryでログ・トレース・メトリクスを連携(れんけい)するとデバッグ効率(こうりつ)が大幅(おおはば)に向上(こうじょう)します。
Q20. マイクロサービス導入時の最も一般的な間違いは何ですか?
- 小(ちい)さすぎるサービス(ナノサービス) 2) 共有(きょうゆう)データベース使用(しよう) 3) 同期(どうき)呼(よ)び出(だ)しチェーンの濫用(らんよう) 4) オブザーバビリティ不備(ふび)でのMSA導入(どうにゅう) 5) チーム構造(こうぞう)変更(へんこう)なしに技術(ぎじゅつ)だけ変更(へんこう) 6) ビッグバンマイグレーション。Conwayの法則(ほうそく)に従(したが)い、チーム構造(こうぞう)がアーキテクチャを決定(けってい)するため、組織(そしき)変化(へんか)が先行(せんこう)すべきです。
15. クイズ
クイズ1. MSAの核心原則でないものは?
A) サービス別独立データベース B) ビジネス能力中心のサービス分離 C) 中央集権的ガバナンス D) 独立デプロイとスケーリング
正解: C
MSAは分散(ぶんさん)ガバナンスを強調(きょうちょう)します。各(かく)チームが自律的(じりつてき)に技術(ぎじゅつ)スタックとデータストアを選択(せんたく)できることが基本(きほん)です。中央集権的(ちゅうおうしゅうけんてき)ガバナンスはSOAの特性(とくせい)です。
クイズ2. Saga Choreographyの欠点は?
A) 中央コーディネーターが単一障害点になる B) ビジネスフローの追跡が困難 C) サービス間結合度が高まる D) イベントブローカーが不要
正解: B
Choreographyは中央(ちゅうおう)コーディネーターなしにイベントベースで動作(どうさ)するため、全体(ぜんたい)のビジネスフロー追跡(ついせき)が困難(こんなん)です。Aは Orchestrationの欠点(けってん)です。
クイズ3. モジュラーモノリスの核心特性でないものは?
A) 単一デプロイ単位 B) モジュール間の公開APIを通じた通信 C) サービス別独立データベース D) 厳格なモジュール境界設定
正解: C
モジュラーモノリスは単一(たんいつ)データベースを使用(しよう)しつつ、モジュール別(べつ)にスキーマを分離(ぶんり)します。サービス別(べつ)独立(どくりつ)データベースはMSAの特性(とくせい)です。
クイズ4. Strangler Figパターンの最初のステップは?
A) レガシーシステムの削除 B) 全機能を新サービスに移行 C) プロキシ/API Gatewayの導入 D) データベース分離
正解: C
Strangler Figパターンの最初(さいしょ)のステップは、トラフィックを制御(せいぎょ)できる単一(たんいつ)エントリポイントを作(つく)るためにプロキシを導入(どうにゅう)することです。
クイズ5. 開発者10名のスタートアップに最適なアーキテクチャは?
A) マイクロサービス B) SOA C) モジュラーモノリス D) Serverless
正解: C
10名(めい)規模(きぼ)のスタートアップにはモジュラーモノリスが最適(さいてき)です。MSAの運用(うんよう)複雑性(ふくざつせい)は負担(ふたん)が大(おお)きく、純粋(じゅんすい)なモノリスよりもモジュール境界(きょうかい)を明確(めいかく)にすることで将来(しょうらい)のサービス分離(ぶんり)に備(そな)えるのが賢明(けんめい)です。
参考資料
- Sam Newman, "Building Microservices" (2nd Edition, O'Reilly 2021)
- Chris Richardson, "Microservices Patterns" (Manning 2018)
- Vaughn Vernon, "Domain-Driven Design Distilled" (Addison-Wesley 2016)
- Spring Modulith公式ドキュメント: https://spring.io/projects/spring-modulith
- Istio公式ドキュメント: https://istio.io/latest/docs/
- OpenTelemetry公式ドキュメント: https://opentelemetry.io/docs/
- Temporal公式ドキュメント: https://docs.temporal.io/
- Martin Fowler, "Microservices": https://martinfowler.com/articles/microservices.html
- DHH, "The Majestic Monolith": https://m.signalvnoise.com/the-majestic-monolith/
- Amazon Prime Video事例研究 (2023)
- Argo Rollouts: https://argoproj.github.io/rollouts/