EXERCISE 90分

ストーリー

高橋アーキテクト がホワイトボードの前に立ちました。

高橋アーキテクト
理論は十分だ。ここからは手を動かそう。あるオンラインフードデリバリーサービスを、マイクロサービスで設計してほしい。通信方式、ゲートウェイ、ディスカバリ、設定管理まで、すべて考えてみよう

ミッション概要

項目内容
題材オンラインフードデリバリーサービス
目標マイクロサービスアーキテクチャを設計する
所要時間90分
成果物アーキテクチャ図、API設計、通信方式の選定理由

ミッション 1: サービスの分割(20分)

以下の機能要件を持つフードデリバリーサービスを、適切なマイクロサービスに分割してください。

機能要件:

  • ユーザー登録・認証
  • レストラン情報の管理・検索
  • メニュー管理
  • 注文の作成・管理
  • 決済処理
  • 配達員のマッチング・配送追跡
  • レビュー・評価
  • プッシュ通知

設計すべきこと:

  1. サービスの一覧と各サービスの責務
  2. 各サービスが所有するデータ
  3. 分割の理由(DDD境界づけられたコンテキスト)
ヒントと模範回答
サービス分割例:

1. Identity Service
   - 責務: ユーザー登録、認証、認可
   - データ: users, roles, tokens

2. Restaurant Service
   - 責務: レストラン情報、メニュー管理
   - データ: restaurants, menus, business_hours

3. Order Service
   - 責務: 注文のライフサイクル管理
   - データ: orders, order_items, order_status

4. Payment Service
   - 責務: 決済処理、返金
   - データ: payments, refunds, payment_methods

5. Delivery Service
   - 責務: 配達員マッチング、配送追跡
   - データ: drivers, deliveries, locations

6. Review Service
   - 責務: レビュー・評価管理
   - データ: reviews, ratings

7. Notification Service
   - 責務: プッシュ通知、メール、SMS
   - データ: notification_templates, notification_logs

分割理由:
- 各サービスは独立した業務ドメイン
- 変更頻度が異なる(メニューは頻繁、認証はまれ)
- スケーリング要件が異なる(検索は高負荷、レビューは低負荷)

ミッション 2: 通信方式の選定(20分)

各サービス間の通信方式(同期/非同期)を決定し、その理由を記述してください。

検討すべき通信:

  1. 注文作成時の在庫確認
  2. 注文確定後の決済
  3. 決済完了後の配達員マッチング
  4. 注文ステータス変更時の通知
  5. レストラン検索
ヒントと模範回答
// 通信方式の選定
const communicationDesign = {
  // 1. 注文 → レストラン: 同期(REST)
  // 理由: メニューの在庫をリアルタイムで確認し、ユーザーに即座に結果を返す
  orderToRestaurant: { type: "sync", protocol: "REST" },

  // 2. 注文 → 決済: 同期(gRPC)
  // 理由: 決済結果を待って注文を確定する必要がある。高速性のためgRPC
  orderToPayment: { type: "sync", protocol: "gRPC" },

  // 3. 注文 → 配送: 非同期(イベント)
  // 理由: 配達員マッチングは時間がかかる。注文確定後に非同期で実行
  orderToDelivery: { type: "async", protocol: "EventBus", event: "order.confirmed" },

  // 4. 各サービス → 通知: 非同期(イベント)
  // 理由: 通知は遅延許容。1つのイベントで複数通知を送信
  anyToNotification: { type: "async", protocol: "EventBus" },

  // 5. クライアント → レストラン検索: 同期(REST)
  // 理由: 検索結果を即座にユーザーに表示
  searchRestaurant: { type: "sync", protocol: "REST" },
};

ミッション 3: API Gateway設計(15分)

API Gatewayの設計を行ってください。

設計すべきこと:

  1. ルーティングテーブル
  2. 認証フロー
  3. レート制限ポリシー
  4. BFFの集約エンドポイント(1つ以上)
ヒントと模範回答
// ルーティングテーブル
const routes = [
  { path: "/api/auth/**",        service: "identity-service",     auth: false },
  { path: "/api/restaurants/**",  service: "restaurant-service",   auth: false },
  { path: "/api/orders/**",       service: "order-service",        auth: true },
  { path: "/api/payments/**",     service: "payment-service",      auth: true },
  { path: "/api/deliveries/**",   service: "delivery-service",     auth: true },
  { path: "/api/reviews/**",      service: "review-service",       auth: true },
];

// レート制限
const rateLimits = {
  anonymous: { requests: 30, window: "1m" },
  authenticated: { requests: 100, window: "1m" },
  premium: { requests: 500, window: "1m" },
};

// BFF集約エンドポイント
app.get("/api/bff/order-summary/:orderId", async (req, res) => {
  const [order, restaurant, delivery] = await Promise.all([
    orderService.getOrder(req.params.orderId),
    restaurantService.getRestaurant(order.restaurantId),
    deliveryService.getDeliveryStatus(req.params.orderId),
  ]);
  res.json({
    order: { id: order.id, items: order.items, total: order.total },
    restaurant: { name: restaurant.name, address: restaurant.address },
    delivery: { status: delivery.status, eta: delivery.estimatedArrival },
  });
});

ミッション 4: サービスディスカバリ設計(15分)

サービスディスカバリとロードバランシングの設計を行ってください。

検討すべきこと:

  1. ディスカバリ方式の選択と理由
  2. ヘルスチェックの設計
  3. ロードバランシングアルゴリズムの選択
ヒントと模範回答
// Kubernetesを前提としたサーバーサイドディスカバリ
// → Kubernetes Serviceが自動的にLBとディスカバリを提供

// ヘルスチェック設計
const healthCheckConfig = {
  // Liveness Probe: サービスが生きているか
  liveness: {
    path: "/health/live",
    interval: 10,       // 10秒ごと
    timeout: 3,          // 3秒でタイムアウト
    failureThreshold: 3, // 3回失敗で再起動
  },
  // Readiness Probe: リクエストを受けられるか
  readiness: {
    path: "/health/ready",
    interval: 5,
    timeout: 3,
    failureThreshold: 2,
  },
};

// ロードバランシング
const lbConfig = {
  restaurantSearch: "round-robin",     // 均等分散
  orderService: "least-connections",    // 処理時間が不均一
  deliveryService: "ip-hash",          // 配達員のセッション維持
};

ミッション 5: 設定管理設計(10分)

分散設定管理の戦略を設計してください。

ヒントと模範回答
// 設定の分類
const configStrategy = {
  // 環境変数(Kubernetes ConfigMap)
  envVars: ["PORT", "LOG_LEVEL", "SERVICE_NAME"],

  // シークレット(AWS Secrets Manager)
  secrets: ["DB_PASSWORD", "API_KEYS", "JWT_SECRET"],

  // 動的設定(AWS AppConfig)
  dynamicConfig: {
    "feature.new_matching_algorithm": { type: "boolean", default: false },
    "config.order_timeout_seconds": { type: "number", default: 300 },
    "config.max_delivery_radius_km": { type: "number", default: 10 },
  },
};

ミッション 6: アーキテクチャ図の作成(10分)

上記すべてを統合したアーキテクチャ図をテキストで描いてください。

ヒントと模範回答
                         [Client App]

                         [API Gateway]
                         ├─ 認証
                         ├─ レート制限
                         └─ BFF集約

              ┌───────────────┼───────────────┐
              │               │               │
         [Identity]     [Restaurant]     [Order]
         [Service]      [Service]        [Service]
              │               │               │
              │               │          ┌────┴────┐
              │               │          │         │
              │               │     [Payment]  [Delivery]
              │               │     [Service]  [Service]
              │               │          │         │
              └───────┬───────┴──────────┴─────────┘

                 [Event Bus]

              ┌───────┴───────┐
              │               │
         [Notification]  [Review]
         [Service]       [Service]

  ── 同期(REST/gRPC)
  ── 非同期(Event Bus)

  横断的関心事:
  [Service Registry] [Config Server] [Secret Manager]

達成チェックリスト

  • 7つ以上のマイクロサービスに適切に分割できた
  • 各通信の同期/非同期を理由とともに選定できた
  • API Gatewayのルーティングと認証を設計できた
  • サービスディスカバリとヘルスチェックを設計できた
  • 設定管理戦略を策定できた
  • 全体のアーキテクチャ図を描けた

推定所要時間: 90分