第05章:Sagaの2方式を知る(Orchestration / Choreography)🧑✈️💃

まずは一言でイメージしよう!🎬✨
- Orchestration(オーケストレーション)=「司令塔がいて、みんなに指示を出す」🧑✈️📣
- Choreography(コレオグラフィー)=「司令塔なし。イベントを見て各自が動く」💃🕺📨
Sagaパターンには、主にこの2つの進め方があるよ〜ってことが公式系の資料でも整理されてるよ📚✨ (microservices.io)
1) たとえ話で一発理解🍔🛒
🧑✈️ Orchestration:レストランの店長方式
- 店長(オーケストレーター)が「注文入ったよ!調理お願い!」→「会計お願い!」→「配達お願い!」って順番に指示📣
- 失敗したら「じゃあ返金ね」「在庫戻してね」って補償も店長が決める🔁
💃 Choreography:フードコートの“呼び出しベル”方式
- 「注文完了イベント」が鳴る🔔
- それを聞いた決済サービスが動いて「決済完了イベント」を出す📨
- それを聞いた在庫サービスが動いて…って連鎖していく✨
- みんなは“ベル(イベント)”だけ見て動く(司令塔はいない)💃
Orchestration(オーケストレーション) 🧑✈️
Choreography(コレオグラフィー) 💃
3) 比較表(メリデメ早見表)📋✨
| 観点 | Orchestration 🧑✈️ | Choreography 💃 |
|---|---|---|
| 全体の流れの分かりやすさ | ✅ かなり分かりやすい(司令塔に集まる) | △ 分かりにくくなりがち(分散) |
| 変更のしやすさ | △ 司令塔の変更が中心(影響は読みやすい) | ✅ 各サービスが独立しやすい(ただし連鎖に注意) |
| 依存関係(結合) | △ 司令塔が各参加者を知りやすい | ✅ publish/subscribeで疎結合になりやすい (Microsoft Learn) |
| 監視・デバッグ | ✅ 追いやすい(中心がある) | △ 追うのが大変(ログ・相関ID必須になりがち) |
| テストのしやすさ | ✅ ワークフローを単体テストしやすい | △ 統合テスト寄りになりがち |
| チーム規模が大きいと… | △ 司令塔がボトルネックになりうる | ✅ チーム自律と相性よい |
Temporalの解説でも、Choreographyは疎結合だけど追いにくく、Orchestrationは観測しやすいが中央集権になりやすい、って整理されてるよ🧠 (temporal.io)
4) ここが超重要:Command と Event の違いを混ぜない🎯📨
- Command(コマンド):お願い・指示(未来)
例:
ReserveInventory(在庫確保して!) - Event(イベント):起きた事実(過去)
例:
InventoryReserved(在庫確保できたよ!)
OrchestrationはCommand中心になりやすいし、ChoreographyはEvent中心になりやすいよ〜って整理がしやすい✨ (milanjovanovic.tech)
5) C#でミニ例:まずは型(メッセージ)を作ろう🔧✨
※ここは“雰囲気を掴む用”のミニコードだよ😊 (実運用はメッセージング基盤・永続化・再試行などが必要になるよ〜)
// Command(お願い)
public sealed record StartOrderSaga(Guid OrderId);
public sealed record ChargePayment(Guid OrderId, decimal Amount);
public sealed record ReserveInventory(Guid OrderId);
public sealed record ShipOrder(Guid OrderId);
// Compensation(補償のお願い)
public sealed record RefundPayment(Guid OrderId);
public sealed record ReleaseInventory(Guid OrderId);
// Event(起きた事実)
public sealed record PaymentCharged(Guid OrderId);
public sealed record PaymentFailed(Guid OrderId, string Reason);
public sealed record InventoryReserved(Guid OrderId);
public sealed record InventoryFailed(Guid OrderId, string Reason);
public sealed record OrderShipped(Guid OrderId);
6) Orchestrationのミニ例:司令塔(オーケストレーター)を書いてみる🧑✈️🧠
ポイントはこれ👇
- 司令塔が「今どの段階?」を覚えて進める(状態)📌
- 失敗したら補償コマンドを出す🔁
public enum SagaStep { None, Payment, Inventory, Shipping, Completed, Compensating, Failed }
public sealed class OrderSagaOrchestrator
{
private readonly IMessageBus _bus;
private SagaStep _step = SagaStep.None;
private Guid _orderId;
private decimal _amount;
public OrderSagaOrchestrator(IMessageBus bus) => _bus = bus;
public Task Handle(StartOrderSaga cmd)
{
_orderId = cmd.OrderId;
_amount = 1200m;
_step = SagaStep.Payment;
return _bus.Send(new ChargePayment(_orderId, _amount));
}
public Task Handle(PaymentCharged ev)
{
if (_step != SagaStep.Payment) return Task.CompletedTask;
_step = SagaStep.Inventory;
return _bus.Send(new ReserveInventory(_orderId));
}
public Task Handle(PaymentFailed ev)
{
// ここは「まだ何も確保してない」ので、補償不要 or 別対応
_step = SagaStep.Failed;
return Task.CompletedTask;
}
public Task Handle(InventoryReserved ev)
{
if (_step != SagaStep.Inventory) return Task.CompletedTask;
_step = SagaStep.Shipping;
return _bus.Send(new ShipOrder(_orderId));
}
public Task Handle(InventoryFailed ev)
{
// 決済は成功してる → 返金で帳尻合わせ
_step = SagaStep.Compensating;
return _bus.Send(new RefundPayment(_orderId));
}
public Task Handle(OrderShipped ev)
{
_step = SagaStep.Completed;
return Task.CompletedTask;
}
}
public interface IMessageBus
{
Task Send<T>(T message);
}
Orchestrationのコツ🌟
- ワークフローが1か所に集まるから、初心者でも追いやすい😊
- ただし「司令塔が全部知ってる」構造になりやすいので、巨大化したら分割が必要🧩
7) Choreographyのミニ例:イベントで連鎖させる💃📨
Choreographyの雰囲気はこんな感じ👇
- 「OrderStarted」イベントを見た決済が動く
- 「PaymentCharged」イベントを見た在庫が動く
- 司令塔はいない(流れが分散する)
public sealed record OrderStarted(Guid OrderId, decimal Amount);
public sealed class PaymentService
{
private readonly IEventBus _bus;
public PaymentService(IEventBus bus) => _bus = bus;
public async Task Handle(OrderStarted ev)
{
var ok = true; // 例:決済できた体にする
if (ok) await _bus.Publish(new PaymentCharged(ev.OrderId));
else await _bus.Publish(new PaymentFailed(ev.OrderId, "Card declined"));
}
}
public sealed class InventoryService
{
private readonly IEventBus _bus;
public InventoryService(IEventBus bus) => _bus = bus;
public async Task Handle(PaymentCharged ev)
{
var ok = true; // 例:在庫確保できた体にする
if (ok) await _bus.Publish(new InventoryReserved(ev.OrderId));
else await _bus.Publish(new InventoryFailed(ev.OrderId, "Out of stock"));
}
}
public interface IEventBus
{
Task Publish<T>(T @event);
}
Choreographyのコツ🌟
- publish/subscribeで疎結合になりやすい💞 (Microsoft Learn)
- でも「どこで何が起きてる?」が散らばりやすいから、ログやトレース設計が重要になりがち🧾🔗
8) 実装フレームワーク例(名前だけ知っておくと強い)🧰✨
「手書きで全部やる」のは大変なので、現場ではライブラリ/基盤を使うことが多いよ〜📦
-
AzureのSagaパターン資料:Sagaの実装方式として choreo/orch の2つを整理してる📚 (Microsoft Learn)
-
MassTransit:
- Saga State Machineは オーケストレーション寄りとして整理されてる📌 (MassTransit Documentation)
- Routing Slipは、分散トランザクション&補償(fault compensation)に寄せた仕組みとして説明されてるよ📦 (masstransit.io)
-
NServiceBus:ワークフロー/サガで“オーケストレーションも、コレオグラフィーも”説明がまとまってるよ📚 (docs.particular.net)
9) やりがち落とし穴コーナー🕳️😵💫(ここ超大事)
落とし穴①:イベントに情報を詰め込みすぎる📦💥
「便利だから全部入れよ!」ってやると、結局イベントが重くなって結合が戻りがち😇 NServiceBusでも「イベントにデータ載せすぎ注意」って方向性が出てるよ⚠️ (docs.particular.net)
落とし穴②:Choreographyが“イベントスパゲッティ”になる🍝
イベントが増えるほど「どれがどれに繋がってるの…?」ってなりやすい😵💫 → ルール:**イベント名は“過去形の事実”**に寄せる、図で管理する🗺️
落とし穴③:Orchestrationの司令塔が“神クラス”化する👑💥
司令塔が何でも知ってて巨大になると、変更が怖くなる😇 → ルール:長いSagaは分割(サブSaga化・境界を切る)🧩
10) どっちを選ぶ?初心者向けの“迷わない判断軸”🧭💡
まず結論(初心者が事故りにくい順)🥇
- Orchestrationから入る🧑✈️(流れが見えるから)
- 慣れてきたら、領域やチーム事情で Choreographyを混ぜる💃
microservices.ioでも「Sagaの協調方法は2つ」って整理されてるよ📚 (microservices.io)
判断チェック✅(YESが多い方に寄せてOK)
Orchestrationに寄せたいとき🧑✈️
- 全体の流れを1つにまとめて管理したい✅
- 補償の分岐が多い✅
- 仕様変更が頻繁で、影響を追いたい✅
Choreographyに寄せたいとき💃
- サービスが多く、各チームが自律してる✅
- 中央の“司令塔”を置きたくない✅
- イベント駆動の文化が整ってる✅
11) ミニ演習(5〜10分)📝😊
演習A:方式を選んで理由を書く🧠✍️
次のケースで、**Orchestration / Choreography どっちが良さそう?**理由も1〜2行で書こう✨
- 小さなEC(注文→決済→在庫→配送)。開発は2人👭
- 大きな組織。決済・在庫・配送は別チームで、リリース頻度も別々🏢
- 補償が複雑(返金だけじゃなく、クーポン、部分返金、手動対応がある)🎫🧾
演習B:イベントとコマンドの分類クイズ🎲
次を Command / Event に分けてみよう😊
CancelOrderOrderCanceledChargePaymentPaymentCharged
12) AI活用(コピペでOK)🤖✨
メリデメ表を作らせる📋
- 「SagaのOrchestrationとChoreographyを、初心者向けに比較表で。観点は“分かりやすさ・変更容易性・監視・テスト・結合度”。」
図にしてもらう🗺️
- 「ECの注文Sagaを、OrchestrationとChoreographyの2種類で、登場メッセージ(Command/Event)込みのシーケンス図にして。」
レビューしてもらう🔍
- 「このイベント設計、情報詰め込みすぎてない?依存が増えそうな点を指摘して、軽量化案も出して。」
13) 今回のまとめ(覚えるのはこの3つだけでOK)🎀✨
- Orchestration=司令塔が指示する🧑✈️
- Choreography=イベントを見て各自が動く💃
- 初心者はまず Orchestrationで“流れ”を掴むのが安心😊
ちなみに、いまのC#は C# 14(.NET 10対応) が最新として案内されてるよ📌 (Microsoft Learn)