アーキテクチャ●●●○○

APIゲートウェイ

API Gatewayエーピーアイゲートウェイ

多数のAPIの手前に立つ単一の入口。認証・流量制御・ルーティングを一手に引き受ける。

概要

APIゲートウェイは、多数の API を提供するシステムの手前に立つ「単一の入口」です。クライアントは個々のバックエンドサービスの場所や構成を知らなくてよく、いつもゲートウェイという一つの窓口にリクエストを送ります。ゲートウェイはそれを適切なサービスへ振り分けると同時に、認証レート制限TLS 終端といった「どのAPIにも共通して必要な処理」を一手に引き受けます。

役所の総合受付をイメージすると分かりやすいでしょう。来訪者は各課の部屋番号を覚える必要がなく、受付で身分確認を済ませれば案内してもらえます。各課は本来の業務に集中でき、受付のルールを変えれば全課に一度に適用できます。マイクロサービスアーキテクチャの実運用では、ほぼ必ずこの層が存在します。代表的な実装・サービスには Kong、Apigee、Amazon API Gateway、Envoy ベースのゲートウェイ群などがあります。

なぜ生まれたか

モノリスの時代、APIの入口は自然と一つでした。ところがマイクロサービスに分割すると、クライアントは苦しみを背負わされます。注文サービス・在庫サービス・ユーザーサービスがそれぞれ別のホストとポートで動いているとき、モバイルアプリは全サービスのアドレスを知り、それぞれと TLS を張り、画面を一つ描くために何往復も通信しなければなりません。モバイル回線では往復のたびに遅延が積み上がります。さらにサービス側の事情 — 分割・統合・移設 — が起きるたびに、配布済みのクライアントが壊れる。内部構造がそのまま外部に露出してしまうのです。

もう一つの苦しみはサービス側にありました。認証、レート制限CORS 対応、アクセスログといった横断的関心事を、全サービスがそれぞれの言語・フレームワークで重複実装することになり、実装漏れは即セキュリティホールになります。「入口を一つに集約し、共通処理はそこでまとめて済ませ、内部構成はその後ろに隠す」— APIゲートウェイは、この二つの苦しみへの答えとして定着しました。

詳細

前段に立つ構成

ゲートウェイはすべての外部リクエストの通り道になり、パスやホスト名に基づいて後段のサービスへルーティングします。共通処理を通過済みのリクエストだけが内部に届くため、各サービスは「認証済み・流量制御済み」を前提にビジネスロジックへ集中できます。

WebアプリモバイルAPIゲートウェイ認証・認可レート制限TLS終端ルーティング・集約ログ・メトリクス注文サービス在庫サービスユーザーサービス外部に見えるのは入口だけ内部構成は自由に変えられる
APIゲートウェイの前段配置 — 横断的関心事を入口で一元処理し、内部構成を隠す

引き受ける横断的関心事

ゲートウェイの仕事は大きく分けて4種類あります。第一にルーティング/orders は注文サービスへ、/users はユーザーサービスへ、といった振り分けに加え、バージョンごとの出し分けやカナリアリリースのような比率制御も担えます。第二にセキュリティTLS 終端、JWT などのトークン検証、APIキー管理を入口で済ませ、WAF と組み合わせて防御の第一線を張ります。第三に流量の制御。クライアントごとのレート制限やクォータで、特定の利用者の暴走や DDoS 的な負荷から後段を守ります。第四に変換と集約。複数サービスへの問い合わせを束ねて1レスポンスにまとめたり、内部の gRPC を外部向けの REST API に変換したり、キャッシュで後段の負荷を減らしたりします。すべてのトラフィックが通る場所なので、メトリクス収集や分散トレーシングの起点としても最適です。

リバースプロキシとの違い

「それはリバースプロキシでは?」という疑問はもっともで、実際、APIゲートウェイはリバースプロキシの一種です。違いは意識するレイヤにあります。汎用のリバースプロキシがホスト名やパスといった HTTP の器を見て中継するのに対し、APIゲートウェイは「これはどのAPIの、どの操作か」を理解した上で動きます。APIごとの認可ポリシー、利用者ごとのクォータ、APIキーの発行・失効、開発者ポータルでの仕様公開 — つまり「APIを製品として管理する」機能まで含むのがゲートウェイです。リバースプロキシが土台で、その上にAPI管理の層を載せたもの、と捉えると位置づけが明確になります。また、外から内への「南北」トラフィックを扱うのがゲートウェイ、サービス間の「東西」トラフィックを扱うのがサービスメッシュ、という役割分担もよく整理に使われます。

BFF — クライアントの種類ごとに入口を分ける

単一のゲートウェイに全クライアントの要望を詰め込むと、モバイル向けの軽量レスポンスとWeb向けの詳細レスポンスが同居して肥大化していきます。そこで、クライアントの種類ごとに専用のゲートウェイ層を立てるのが BFF(Backend for Frontend)パターンです。モバイル用BFFは画面に必要な情報だけを集約して返し、Web用BFFは SPA に合わせた形に整える。各BFFはそれを使うフロントエンドチームが所有するため、「どのクライアントの都合を優先するか」という綱引きも解消されます。近年は BFF に GraphQL を採用し、クライアント自身が必要なデータの形を宣言できるようにする構成も人気です。

落とし穴 — 単一障害点と太りすぎ

すべてのトラフィックが一点を通る構成は、そのまま弱点にもなります。ゲートウェイが落ちれば全APIが落ちるため、冗長化とスケーリング、そして自身のヘルスチェックは必須です。また全リクエストに1ホップ分の遅延が加わることも忘れてはいけません。もう一つの古典的な失敗が「太りすぎゲートウェイ」です。便利な場所ゆえにビジネスロジックが少しずつ染み出し、気づけばゲートウェイ自体が巨大なモノリスと化して、全チームの変更がそこで渋滞する — これでは何のためにサービスを分割したのか分かりません。ゲートウェイに置いてよいのは横断的関心事まで、ドメインのロジックは後段のサービスに、という線引きを守り続けることが、この構成を健全に保つ鍵になります。