🎄 科学と神々株式会社 アドベントカレンダー 2025
Hybrid License System Day 2: マイクロサービスアーキテクチャとは何か?
マイクロサービス基礎編 (1/4)
📖 はじめに
Day 2では、マイクロサービスアーキテクチャの基礎を学びます。モノリシックなアプリケーションとの違いや、マイクロサービスがもたらす利点と課題を理解しましょう。
🏛️ モノリシック vs マイクロサービス
モノリシックアーキテクチャ
定義: すべての機能が単一のアプリケーションにまとまっている構造
┌─────────────────────────────────┐
│ Monolithic Application │
│ │
│ ┌───────────────────────────┐ │
│ │ User Management │ │
│ ├───────────────────────────┤ │
│ │ Authentication │ │
│ ├───────────────────────────┤ │
│ │ License Management │ │
│ ├───────────────────────────┤ │
│ │ Admin Dashboard │ │
│ ├───────────────────────────┤ │
│ │ Database Layer │ │
│ └───────────────────────────┘ │
│ │
│ Single Deployment Unit │
└─────────────────────────────────┘
利点:
- ✅ シンプルなデプロイメント(1つのアプリケーション)
- ✅ 開発初期は高速に進められる
- ✅ トランザクション管理が簡単
- ✅ デバッグが容易
課題:
- ❌ スケーリングが非効率(全体をスケールする必要)
- ❌ 一部の変更でも全体を再デプロイ
- ❌ 技術スタックの変更が困難
- ❌ 大規模化すると保守性が低下
- ❌ 障害の影響が全体に及ぶ
マイクロサービスアーキテクチャ
定義: 機能ごとに独立したサービスに分割し、疎結合で連携する構造
┌──────────────────────────────────────────────────┐
│ Microservices Architecture │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ API Gateway │ │ Auth Service│ │ Admin │ │
│ │ (Port │ │ (Port │ │ Service │ │
│ │ 3000) │ │ 3001) │ │ (Port │ │
│ │ │ │ │ │ 3002) │ │
│ │ - Routing │ │ - JWT │ │ - Users │ │
│ │ - CORS │ │ - BCrypt │ │ - Stats │ │
│ │ - Rate │ │ - DB Ops │ │ - Audit │ │
│ │ Limiting │ │ │ │ Logs │ │
│ └──────┬──────┘ └──────┬──────┘ └────┬─────┘ │
│ │ │ │ │
│ └────────────────┴────────────────┘ │
│ │ │
│ ┌─────────▼──────────┐ │
│ │ Shared Database │ │
│ │ (SQLite) │ │
│ └────────────────────┘ │
│ │
│ Independent Deployment Units │
└──────────────────────────────────────────────────┘
利点:
- ✅ 独立したスケーリング(必要なサービスのみ)
- ✅ 部分的なデプロイ(影響範囲が限定的)
- ✅ 技術スタックの自由度が高い
- ✅ 障害の影響が局所化
- ✅ チームの独立性が高い
課題:
- ❌ システム全体の複雑性が増す
- ❌ 分散トランザクションの管理が難しい
- ❌ サービス間通信のオーバーヘッド
- ❌ デバッグが複雑化
- ❌ 運用コストが増加
🎯 いつマイクロサービスを選ぶべきか?
マイクロサービスが適している場合
-
スケーラビリティが重要
- 特定の機能に負荷が集中する
- トラフィックが予測不可能
- 地理的に分散したユーザー
-
複数のチームで開発
- 大規模な開発組織
- チーム間の独立性が必要
- 異なる技術スタックを使いたい
-
頻繁なリリースが必要
- 継続的デプロイメント
- カナリアリリース
- A/Bテスト
-
ドメインが明確に分離可能
- 認証、決済、通知などの独立した機能
- それぞれが独立したビジネス価値を持つ
モノリシックが適している場合
-
小規模なアプリケーション
- チームが小さい(5人以下)
- 機能が限定的
-
初期フェーズ
- ビジネスモデルが未確定
- 迅速なプロトタイピングが必要
-
シンプルなドメイン
- 機能が密結合している
- 分離するメリットが少ない
🏗️ Hybrid License Systemのアーキテクチャ
サービス分割の理由
Hybrid License Systemでは、以下の3つのマイクロサービスに分割しています:
1. API Gateway (Port 3000)
責務: すべてのクライアントリクエストの受付窓口
// src/server.js (簡略版)
const express = require('express');
const app = express();
// 認証関連のリクエストをAuth Serviceに転送
app.post('/api/v1/license/activate', (req, res) => {
// Auth Serviceにプロキシ
proxyToAuthService(req, res);
});
// 管理関連のリクエストをAdmin Serviceに転送
app.get('/api/v1/admin/stats', (req, res) => {
// Admin Serviceにプロキシ
proxyToAdminService(req, res);
});
分離理由:
- クライアントからの統一エントリーポイント
- バックエンドサービスの構成変更から隔離
- 横断的関心事(CORS、レート制限)の一元管理
2. Auth Service (Port 3001)
責務: ライセンス認証とユーザー管理
// src/authService.js (簡略版)
class AuthService {
async activate(email, password, clientId) {
// ユーザー認証
const user = await this.authenticateUser(email, password);
// ライセンス生成
const license = await this.createLicense(user, clientId);
// JWT生成
const token = this.generateJWT(user, license);
return { token, license };
}
}
分離理由:
- セキュリティが重要な機能を隔離
- 独立したスケーリング(認証リクエストが多い)
- BCrypt/JWT処理の専門化
3. Admin Service (Port 3002)
責務: 管理ダッシュボードと統計API
// src/routes/stats.js (簡略版)
router.get('/stats', async (req, res) => {
const stats = {
totalUsers: await getUserCount(),
activeLicenses: await getActiveLicenseCount(),
revenue: await calculateRevenue()
};
res.json(stats);
});
分離理由:
- 管理機能とユーザー向け機能の分離
- ダッシュボードの独立した進化
- 管理者権限の明確な境界
📊 マイクロサービスアーキテクチャのメリット(実例)
1. 独立したスケーリング
# Kubernetesでの独立スケーリング例
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
spec:
replicas: 5 # Auth Serviceは5インスタンス
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-service
spec:
replicas: 2 # Admin Serviceは2インスタンス
シナリオ: ライセンス認証のピークタイムにAuth Serviceのみスケールアップ
2. 部分的なデプロイ
# Admin Serviceのみ更新
docker-compose up -d --build admin-service
# Auth Serviceは影響を受けない
curl http://localhost:3001/health
# → {"status": "healthy"}
シナリオ: ダッシュボード機能の追加時、認証機能には影響なし
3. 障害の局所化
// API Gatewayでのサーキットブレーカーパターン
const circuitBreaker = new CircuitBreaker(async () => {
return await fetch('http://admin-service:3002/stats');
}, {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
});
// Admin Serviceが停止しても、Auth Serviceは正常動作
app.get('/api/v1/admin/stats', async (req, res) => {
try {
const stats = await circuitBreaker.fire();
res.json(stats);
} catch (error) {
res.status(503).json({ error: 'Admin service unavailable' });
}
});
🚀 次のステップ
Day 3では、サービス分割の設計原則について学びます。ドメイン駆動設計(DDD)の基礎と、Bounded Contextの考え方を理解しましょう。
🔗 関連リンク
次回予告: Day 3では、なぜAuth/Admin/Gatewayという分割にしたのか、その設計思想を掘り下げます!
Copyright © 2025 Gods & Golem, Inc. All rights reserved.