15個のマイクロサービスがあった。それぞれが独自の認証を実装していた。それぞれが独自のリトライロジックを持っていた。それぞれが異なるログの出し方をしていた。何か壊れると、サービス間のログを相関させるのに何時間も費やした。
そして1つの遅いサービスがカスケード障害を引き起こした。他のサービスは積極的にリトライした。遅いサービスはさらに遅くなった。すべてが崩壊した。
2つのものが欠けていた:エッジのAPIゲートウェイと、内部のサービスメッシュだ。
ゲートウェイはクラブのバウンサーみたいなものだ。インターネットからのすべてはまずゲートウェイを通る。身分証明書をチェックし、問題を起こしていないか確認し、それから初めて実際のサービスに通す。
認証はエッジで一度だけ。 内部サービスはトークンを再チェックする必要がない。リクエストがゲートウェイを通過したなら、認証済みだ。これだけで大量の重複コードがなくなる。
レート制限は悪意あるクライアントをサービスに到達する前に止める。 あるIPから毎分10Kリクエストが来てる?エッジでブロック。サービスはそのトラフィックを見ることすらない。
リクエストルーティングが簡単になる。 APIのバージョニングをしたい?/api/v1/usersを古いサービスに、/api/v2/usersを新しいサービスにルーティング。Blue-Greenデプロイ?ルーティング設定を切り替えるだけ。
SSLはエッジで終端する。 HTTPSは一度だけ処理して、内部トラフィックはプレーンHTTPでいい—より速くてシンプル。ゲートウェイがすべての証明書を保持する。
ゲートウェイがないと、すべてのサービスが攻撃対象になる。すべてのサービスに認証ロジックが必要になる。すべてのサービスが独自のレート制限を処理する。結果として、同じものの微妙に異なる実装が15個できて、それぞれに異なるバグがある。
Kong、AWS API Gateway、Nginx—どれでもいい。同じ問題を解決する。
ゲートウェイは外部トラフィックを処理する。ではサービスAがサービスBを呼び、サービスBがサービスCを呼ぶときは?
メッシュなしで何が起こるか。Cが遅くなる。BはCを待っているから、Bのスレッドが溜まり始める。BはAに応答できない。Aがタイムアウトし始める。1つの遅いサービスが3つを巻き込んだ。
メッシュありだと話が変わる。Cが遅くなると、サーキットブレーカーが開く。Bは永遠に待つ代わりにすぐフォールバックレスポンスを返す。Aは健全なまま。影響範囲は実際に壊れている1つのサービスに封じ込められる。
メッシュはバジェット付き自動リトライを提供する—失敗したリクエストをリトライするが、総リトライ数を制限してリトライストームを作らない。障害を起こしているサービスへのトラフィックを止めて回復させるサーキットブレーカーがある。
どこでもmTLSがあり、すべての内部トラフィックを暗号化する。自分のネットワーク内でもゼロトラスト。あるサービスが別のサービスになりすますことはできない。
オブザーバビリティが組み込みで付いてくる。 すべての呼び出しがトレースされる。リクエストIDがチェーン全体を流れる。レイテンシが跳ね上がったら、どのホップが遅いか正確に見える。
トラフィックシフティングはデプロイの恐怖を減らす。新バージョンを5%のトラフィックにデプロイする。メトリクスを監視する。良ければロールフォワード、悪ければロールバック。
Istio、Linkerd、AWS App Mesh—各サービスの横にサイドカープロキシを注入することで機能する。プロキシがすべてのネットワークロジックを処理する。アプリケーションコードはシンプルなまま。
ゲートウェイはいわゆるNorth-Southトラフィック—外部から入ってくるリクエストを処理する。認証、レート制限、APIバージョニング、SSL、リクエスト変換を扱う。
メッシュはEast-Westトラフィック—インフラ内部のサービス間呼び出しを処理する。mTLS、リトライバジェット、サーキットブレーキング、分散トレーシング、トラフィック分割を管理する。
ゲートウェイはシステムを外部から守る。メッシュはシステムを自分自身から守る。
どちらも必要。異なる問題。
モノリスを運用しているなら、おそらくどちらも必要ない。レート制限が欲しければゲートウェイかもしれないが、メッシュは確実にいらない。
3-5サービスなら、ゲートウェイは意味がある。認証の一元化には価値がある。でもリトライはまだ手動で管理できて、それほど苦しくない。
10サービス以上になったら、両方必要だ。メッシュなしの運用複雑さは凶悪になる。すべてのインシデントが何時間ものログ相関になる。
50サービス以上なら、メッシュはオプションではない—必須だ。分散トレーシングなしではインシデントが文字通りデバッグ不能になる。何が起こったか把握するのに、実際に直すより長い時間がかかる。
これらは贅沢品ではない。マイクロサービスをスケールで生き延びさせるものだ。
メッシュなしのマイクロサービスは、ただの分散デバッグだ。
— blanho
— blanho
CRUDは履歴を上書きする。イベントソーシングはすべてを記憶する。それが重要な場面とオーバーキルな場面。
冗長パイプライン、インテリジェントなセグメント選択、カスタムストレージレイヤー — Netflix Live Originアーキテクチャの内側。
ロギング、認証、リトライ、レート制限 — 最初に設計しないが、後で全員が苦しむもの。