
はじめに
マイクロサービスは単に「モノリスを分割する」だけではありません。間違った方法で分割すると、両方のアーキテクチャのすべての欠点を伴う「分散モノリス」が作成されます。この記事では、マイクロサービスを適切に分割するための設計原則について説明します。
1. マイクロサービスとは何ですか?
マイクロサービスは、アプリケーションが多数の小さな独立したサービスで構成される アーキテクチャ スタイルです。
Monolith Microservices
┌──────────────────────┐ ┌──────────┐ ┌──────────┐
│ Một ứng dụng │ │ Order │ │ Payment │
│ ┌──────┐ ┌──────┐ │ │ Service │ │ Service │
│ │Order │ │Payment│ │ → └──────────┘ └──────────┘
│ ├──────┤ ├──────┤ │ ┌──────────┐ ┌──────────┐
│ │Invent│ │Notif │ │ │Inventory │ │ Notif │
│ └──────┘ └──────┘ │ │ Service │ │ Service │
│ Shared Database │ └──────────┘ └──────────┘
└──────────────────────┘ Mỗi service có DB riêng
機能
- 別のプロセスで実行: 各サービスは独立したプロセス/コンテナです
- ネットワーク通信: HTTP/REST、gRPC、メッセージキュー
- 独立した展開: サービス B に影響を与えずにサービス A を展開します。
- プライベート データベース: サービスごとのデータベース パターン
- 小規模チーム: 1 ~ 3 つのサービスを所有する 2 つのピザ チーム (5 ~ 8 人)
2. 単一責任原則 (SRP)
各サービスは 1 つの操作のみを担当し、変更する理由は 1 つあります。
✅ Đúng — Mỗi service một nghiệp vụ rõ ràng:
├── OrderService → Quản lý vòng đời đơn hàng
├── PaymentService → Xử lý thanh toán
├── InventoryService → Quản lý tồn kho
├── NotificationService → Gửi email/SMS/push
└── UserService → Quản lý tài khoản
❌ Sai — Service "thùng rác":
├── OrderPaymentService → 2 nghiệp vụ gộp
├── CommonService → Mọi thứ chung
└── UtilityService → Không rõ trách nhiệm
SRP違反の兆候
- サービスに 無関係な API エンドポイントが多すぎます
- 機能 A を変更するには、機能 B を再テストする必要があります
- 多くのチームが同じサービスを修正する
- サービス名に「and」または「util」または「common」が含まれる
3. ドメイン駆動設計 (DDD)
3.1 なぜ DDD が必要なのでしょうか?
DDD は、「各サービスの境界はどこですか?」 という最も重要な質問に答えるのに役立ちます。
DDD では、技術 (フロントエンド サービス、バックエンド サービス、データベース サービス) ごとに分割するのではなく、ビジネス ドメイン ごとに分割します。
3.2 戦略的設計
ユビキタス言語
開発者とドメイン専門家の間で 共通言語を構築します。
Domain Expert (Business): Developer (Tech):
"Đơn hàng" → Order
"Thanh toán" → Payment
"Giao hàng" → Shipment
"Hoàn tiền" → Refund
"Kho hàng" → Inventory
Đảm bảo: Code, API, database, documentation đều dùng cùng thuật ngữ
境界付きコンテキスト
境界コンテキストは、モデルが意味を持つ範囲を定義します。
┌──────────────────────────────────────────────────────┐
│ E-Commerce System │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │
│ │ Order │ │ Catalog │ │ Customer │ │
│ │ Context │ │ Context │ │ Context │ │
│ │ │ │ │ │ │ │
│ │ "Product" │ │ "Product" │ │ "Customer" │ │
│ │ = OrderItem │ │ = SKU with │ │ = Account │ │
│ │ (id, qty, │ │ specs, │ │ with prefs, │ │
│ │ price) │ │ images, │ │ addresses │ │
│ │ │ │ pricing │ │ │ │
│ └─────────────┘ └─────────────┘ └──────────────┘ │
│ │
│ Cùng từ "Product" nhưng ý nghĩa KHÁC NHAU │
│ trong mỗi Bounded Context │
└──────────────────────────────────────────────────────┘
重要なルール: 境界付けられた各コンテキスト → 1 つ (または複数) のマイクロサービス。
3.3 コンテキストのマッピング — コンテキスト間の関係
┌─────────────┐ Published ┌──────────────┐
│ Order │────Language────▶│ Payment │
│ Context │ │ Context │
└──────┬──────┘ └──────────────┘
│
│ Customer/Supplier
▼
┌─────────────┐ Conformist ┌──────────────┐
│ Shipping │◀───────────────│ 3rd Party │
│ Context │ │ Logistics │
└─────────────┘ └──────────────┘
| 関係 | 説明 |
|---|---|
| 共有カーネル | 2 つのコンテキストがサブセット コード/モデルを共有する |
| 顧客/サプライヤー | 上流は API を提供し、下流は消費します。 |
| 適合者 | ダウンストリームはアップストリーム モデルに完全に準拠 |
| 腐敗防止層 | 外部モデルと内部モデルの間の変換層 |
| 公開言語 | 標準形式 (JSON スキーマ、Protobuf) で通信する |
3.4 戦術的設計 — 構成要素
Bounded Context
│
├── Entity → Có identity, lifecycle (Order, User)
├── Value Object → Không có identity, immutable (Money, Address)
├── Aggregate → Cluster of entities, consistency boundary
│ └── Aggregate Root → Entry point (Order là root, OrderItem là child)
├── Domain Event → Sự kiện nghiệp vụ (OrderCreated, PaymentReceived)
├── Repository → Persistence abstraction
└── Domain Service → Logic không thuộc entity nào (PricingCalculator)
集計 — 一貫性ユニット
Order Aggregate:
┌───────────────────────────────┐
│ Order (Aggregate Root) │
│ ├── id: "O-001" │
│ ├── status: "confirmed" │
│ ├── total: $500 │
│ │ │
│ ├── OrderItem │
│ │ ├── product: "iPhone" │
│ │ ├── qty: 1 │
│ │ └── price: $400 │
│ │ │
│ ├── OrderItem │
│ │ ├── product: "Case" │
│ │ ├── qty: 1 │
│ │ └── price: $100 │
│ │ │
│ └── ShippingAddress │
│ └── "123 ABC Street" │
└───────────────────────────────┘
Quy tắc:
- Chỉ truy cập thông qua Aggregate Root (Order)
- Một transaction = một aggregate
- Cross-aggregate = eventual consistency
4. 疎結合と高い凝集性
4.1 疎結合
サービス A を変更しても、サービス B を変更する必要はありません**。
✅ Loose Coupling:
Order Service ──event──▶ Kafka ──▶ Payment Service
(Thay đổi internal logic của Order → Payment không bị ảnh hưởng)
❌ Tight Coupling:
Order Service ──direct DB query──▶ Payment Database
(Thay đổi schema Payment DB → Order Service bị broken)
4.2 高い凝集性
関連機能は1つのサービスにグループ化されています。
✅ High Cohesion:
Payment Service:
├── ProcessPayment()
├── RefundPayment()
├── ValidateCard()
└── GetPaymentHistory()
→ Tất cả đều liên quan đến "thanh toán"
❌ Low Cohesion:
MiscService:
├── ProcessPayment()
├── SendEmail()
├── GenerateReport()
└── ResizeImage()
→ Không liên quan gì đến nhau
5. マイクロサービスを使用すべき/使用すべきでないのはどのような場合ですか?
5.1 は次の場合に使用する必要があります。
- ✅ 大規模 システム、多くのチームが並行して開発
- ✅ システムの各部分を個別に拡張する必要がある
- ✅ 多言語対応 (複数の言語/フレームワーク) が必要です
- ✅ 迅速なリリース サイクル、継続的な展開
- ✅ 明確な境界を持つ複雑なドメイン
- ✅ 組織は DevOps の成熟度 (CI/CD、モニタリング、コンテナ オーケストレーション) を備えています
5.2 次の場合は使用しないでください。
- ❌ チーム 小規模 (< 5 人)
- ❌ シンプル アプリケーション、それほど複雑ではないドメイン
- ❌ 明確に理解されていない ドメイン境界
- ❌ CI/CD インフラストラクチャとコンテナ オーケストレーションなし
- ❌ 開発期間は限られています
- ❌ チームには分散システムの運用経験がない
5.3 Monolith First
Martin Fowler は 「モノリス ファースト」 を推奨しています。
Phase 1: Monolith
├── Hiểu rõ domain
├── Phát triển nhanh
└── Xác định boundary tự nhiên
Phase 2: Modular Monolith
├── Tách module rõ ràng trong monolith
├── Mỗi module có boundary riêng
└── Giao tiếp qua internal API
Phase 3: Microservices (khi cần)
├── Tách module thành service
├── Thêm API Gateway
└── Event-driven communication
6. アンチパターンは避けるべきです
Distributed Monolith
❌ Chia thành nhiều service nhưng:
- Deploy phải đồng thời tất cả
- Shared database
- Synchronous chain calls dài
- Tightly coupled API contracts
→ Có đầy đủ nhược điểm của cả Monolith VÀ Microservices
→ Không có ưu điểm của cái nào cả
ナノサービス (小さすぎる)
❌ Chia quá nhỏ:
├── CreateOrderService
├── UpdateOrderService
├── DeleteOrderService
├── GetOrderService
└── ListOrderService
→ Quá nhiều service, overhead network, khó quản lý
→ Nên gom thành: OrderService
7. まとめ
| 原則 | キーポイント |
|---|---|
| 希望小売価格 | 各サービスにはビジネスがあり、変更する理由があります。 |
| DD | 技術ではなく境界コンテキストに従ってサービスを分割する |
| 集計 | 整合性ユニット、集約ルート経由でアクセス可能 |
| 疎結合 | サービス A を変更してもサービス B には影響しません。 |
| 高い凝集力 | 関連する機能を 1 つのサービスにグループ化 |
| モノリスファースト | モノリスから始めて、ドメインを理解したら徐々に分離 |
次の記事: 同期通信 — REST API と gRPC、マイクロサービス間の同期通信で最も一般的な 2 つのプロトコル。