チームにマイクロサービスを描いてもらうと、たいてい同じ絵が出てきます。30 個のボックスがすべて互いにつながり、矢印にはラベルがありません。図としては正確でも、誰の疑問にも答えていません。エンジニアはこれを「デススター図」と呼びます。
役に立つマイクロサービスのアーキテクチャ図とは、何を見せるかについての判断を積み重ねたものです。このガイドでは、5 つのサービスからなるオンラインストアを例に、図を読みやすくする 7 つのルールを説明します。同じルールは、サービスが 5 つでも 50 でも通用します。
図が答えるべき問い
描き始める前に、問いを書き出しましょう。よいマイクロサービス図は、次の 5 つの問いにひと目で答えます。
- リクエストはどこから入ってくるのか? クライアント、API ゲートウェイ、BFF(Backends for Frontends)です。
- どのサービスがどのデータを所有しているのか? どのデータベースにも、所有者はちょうど 1 つであるべきです。
- 誰が誰を同期的に呼び出しているのか? こうした呼び出しでは、レイテンシーも障害も共有されます。
- 何が非同期に起きるのか? イベントとキューは、サービス同士を時間的に切り離します。
- 自分たちの管理外にあるものは何か? 決済プロバイダー、メールサービス、パートナーの API などです。
ボックスや矢印がこれらの問いのどれにも役立たないなら、それはおそらく別の図に載せるべきものです。
例: 5 つのサービスからなるオンラインストア
このストアには、Web とモバイルのクライアント、API ゲートウェイ、そして 5 つのサービスがあります。
- Catalog は、自前の PostgreSQL データベースから商品を提供します。
- Cart は、カートを Redis に保持します。
- Orders は、自前の PostgreSQL データベースに注文を作成し、Kafka の
ordersトピックにOrderPlacedを発行します。 - Payments は、
OrderPlacedを購読して Stripe でカード決済を行い、結果を保存して、paymentsトピックにPaymentSucceededまたはPaymentFailedを発行します。 - Notifications は、
paymentsトピックを購読し、メールプロバイダー経由で領収書、または決済失敗の通知をメールで送ります。
Orders も、注文を支払い済みにするために payments トピックを購読します。Payments を直接呼び出すサービスはなく、チェックアウトの流れはイベントの連鎖になっています。この設計上の選択こそ、図で見えるようにしなければならないものです。
ダイアグラムの内容
- Web and mobile clients
- API gateway
- Catalog
- Cart
- Orders
- Catalog DB
- Cart store
- orders topic
- Orders DB
- Payments
- Stripe
- Payments DB
- payments topic
- Notifications
- Email provider
- HTTPS
- GET /products
- /cart
- POST /orders
- SQL
- RESP
- OrderPlaced
- group: payments
- PaymentSucceeded / PaymentFailed
- group: orders
- group: notifications
- SMTP
図は左から右へ読みます。入口はゲートウェイだけで、実線の矢印は同期呼び出し、破線の矢印は名前付きトピックを経由するイベントです。そして、どのデータベースもちょうど 1 つのサービスにぶら下がっています。
読みやすいマイクロサービス図のための 7 つのルール
1. 入口から描き始める
まず左側に、クライアントと API ゲートウェイを描きます。これらが読む方向の起点になり、そもそもどのサービスが外部に公開されているのかを示します。ゲートウェイからの経路がないサービスは内部向けであり、それが見えること自体に価値があります。
2. 各データベースを所有者につなぐ
各データストアは、それを所有する唯一のサービスの隣に置き、そのサービスとだけ接続します。いま 2 つのサービスが 1 つのデータベースを共有しているなら、それもそのまま描きます。これはよく知られた危険信号であり、それを隠した図では次の移行を計画しにくくなります。
3. 同期呼び出しとイベントを分ける
線のスタイルを 2 種類使い、凡例で明示します。リクエストとレスポンス(REST、gRPC)は実線、ブローカーを経由するメッセージは破線です。トピックやキューはノードとして描きます。すべてのサービスがつながった「イベントバス」のボックスが 1 つあるだけでは、誰が何を発行し、誰が何を購読しているのかが隠れてしまいます。
4. すべてのエッジに、流れるものをラベルとして付ける
GET /products、POST /orders、OrderPlaced、PaymentFailed。ラベルは矢印を契約に変えます。そして障害対応の最中に、人が図の中で探すのはまさにこのラベルです。
5. 技術ではなくドメインでまとめる
フレームが必要なら、サービスをビジネスドメインや担当チームでまとめます。たとえば、ショッピング、チェックアウト、顧客コミュニケーションです。「Node.js のサービス」「Java のサービス」のようなフレームは、誰も尋ねない問いに答えているにすぎません。
6. インフラは別のビューに分ける
Pod、サイドカー、サービスメッシュ、ダッシュボードは重要ですが、論理ビューに載せるものではありません。デプロイメントは Kubernetes のアーキテクチャ図 のような別の図に描き、2 つの図を相互にリンクします。
7. 重要なフローを 1 つだけ示す
売上を支えるフロー、ここではチェックアウトを選び、たどりやすくします。エッジ上の手順に番号を振るか、その経路を強調しましょう。図 1 枚につきフローは 1 つです。2 つ目のフローには、そのビューのコピーを別に用意します。
システムが 1 枚の図に収まらないとき
ボックスが 20 個ほどを超えたら分割します。うまくいくパターンは次のとおりです。
- 全体像の図を 1 枚。 ドメインをフレームとして描き、ドメイン間の最も重要なつながりだけを載せます。
- ドメインごとに 1 枚の図。 そのドメインのサービス、データストア、トピックを、上のルールに沿って描きます。
- フロー図。 チェックアウトやサインアップなど、重要な少数のジャーニーについて描きます。
これは C4 モデル にきれいに対応します。全体像の図はシステムコンテキストのビューに近く、各ドメインの図は、サービスとそのデータベースをコンテナとして描くコンテナビューにあたります。
よくある間違い
- ラベルのない矢印。 読み手は推測するしかなく、しかも人によって推測が違います。
- ゲートウェイがデータベースにつながっている。 ゲートウェイが本当にデータベースを読んでいるなら、それは図の上の近道として描くものではなく、議論すべき設計判断です。
- ビューの混在。 Pod、AWS のサービス、ビジネスケイパビリティを 1 つのキャンバスに載せると、どれも読めなくなります。
- ブローカーを隠す。 Kafka はただのパイプではありません。トピックには名前、所有者、コンシューマーがあります。
- 更新されないスナップショット。 前回のアーキテクチャ刷新のときの図は、もはや歴史資料です。日付を入れるか、常に最新の状態に保ちましょう。
Archboard で描く
Archboard には、この図の各要素に対応するノードパックがあります。そのため、サービス、ストア、トピックは、見た目が同じボックスではなく、ポートを持つ型付きのノードになります。
- Google または GitHub でサインインし、図を作成します。
- クライアント用に基本パックから ボックス を、クラウドパックから APIゲートウェイ を追加します。
- サービスは C4 モデルパックの コンテナ ノードとして追加し、言語やフレームワークを「技術」フィールドに入力します。
- データパックから Postgres と Redis をそれぞれの所有者の隣に追加し、
ordersとpaymentsには トピック ノードを追加します。 - Stripe とメールプロバイダーには、C4 モデルパックの 外部システム ノードを追加します。
- ポートを接続します。同期呼び出しは実線のままにし、イベントは破線に変えてから、すべてのエッジにラベルを付けます。
- ライブリンクをチームと共有するか、Pro ならドキュメントに埋め込みます。
上の例はダイアグラムノードが 15 個なので、Free プランに収まります。関連する例として、デプロイメント側は /examples/kubernetes-microservices、ゲートウェイパターンのインフォグラフィックは /examples/api-gateway-infographic を開いてみてください。
よくある質問
1 枚の図に、いくつのサービスを載せるべきですか? ズームせずに読める数までです。通常はボックス 20 個程度が目安です。それを超えたらドメインごとに分割し、その上に全体像のビューを置きます。
マイクロサービスに C4 モデルを使うべきですか? 相性はよいです。サービスとそのデータベースは、コンテナビューの中のコンテナになります。独立して所有されるサービスを、それぞれ 1 つのソフトウェアシステムとしてモデル化するチームもあります。どちらかの規約を選び、文書に残してください。
Kubernetes、サービスメッシュ、監視はどう表せばよいですか? 別のデプロイメント図に描きます。論理ビューは「誰が誰と通信するか」に答え、デプロイメントビューは「どこで動くか」に答えます。
コンシューマーはプルするのだから、イベントの矢印はコンシューマーからトピックへ向けるべきですか? データが流れる向き、つまりプロデューサーからトピック、トピックからコンシューマーへと描きます。議論のうえで重要なら、コンシューマーがプルすることを注記しておきます。
図を最新に保つにはどうすればよいですか? 図のオーナーを決め、変更と同じプルリクエストで更新し、スクリーンショットを貼る代わりに、ドキュメントからライブの図にリンクします。