前回は、APIの認証と認可をスケールする手法について説明した。第3回の本稿では、APIのキャッシュの活用と過度なリクエストを制御する手法について解説しよう。
エッジでAPIのアクセスを制御するモチベーションの1つがキャッシュであり、特に検索系APIでは有効だ。エッジでAPIキーやJWT(JSON Web Token)を検証し、認可されたリクエストのみがオリジンのAPIサーバにフォワードされるが、毎回オリジンにリクエストが届くと、ユーザー体験が悪くなってしまう。以下に、APIのレスポンスをキャッシュすべき7つの理由を挙げる。
- 多くのAPIは読み取りに対するリクエストである
- バックエンドのデータベースが変わらなければ応答結果も変わらない
- クラウド基盤はIOPSとインスタンスサイズで請求する
- ネットワークトラフィックを削減できる
- データベースのクエリ/計算コストを削減できる
- オリジンのサーバが停止した場合でもキャッシュされたエッジで応答できる
- 全体のネットワーク帯域での制約の上限を超えず、正規クライアントからのAPIを拒否しない
代表的なAPIキャッシュの機能としては次の分類となる。
上図は、アカマイのAPI GatewayのAPIキャッシュ画面例となる。ドメイン単位だけでなく、リソースパス単位で細かく制御する。画面の設定では、「/add」のリソースパスに対して10分間のキャッシュを行い、オリジンのサーバがダウンしていてもキャッシュからレスポンスを返す。キャッシュキーにはクエリ文字のaとbパラメータが含まれ、内容には正確性を求められるという具合である。
またドメイン、リソース単位だけでなく、JWTのクレーム(属性情報)の値単位でキャッシュすることもできる。JWTを検証した後、属性に応じて返されるレスポンスがエッジでキャッシュできるとAPIサーバに対するアクセスを削減できる。JWTに関しては認可、キャッシュだけでなく、ルーティングのユースケースもある。クレームの値に応じて、バックエンドのマイクロサービスのルーティングを可変にするようなケースだ。
なお、仮に全くキャッシュできない動的なコンテンツを返すAPIがあったとしても、Akamaiの場合には「SureRoute」というインターネット網を安定して高速に配信する機能も提供している。
こうしてエッジでのアクセス制御ができると、キャッシュだけでなくクライアントを意識した流量制御が行える。ある時間軸の中でAPIコンシューマーが作り出すリクエストの量を制限することは、ガバナンスの観点でも重要だ。APIリクエスト数を制御する2つの代表的な方法に「レート制限」と「クォータ管理」がある。両者は似ているが、別の特徴を持つ異なる機能だ。
レート制御は、想定外のリクエストからインフラを守りながら、通常のクライアントからのAPIリクエストを処理できるようにするのが目的となる。比較的短い時間軸の中で、リクエスト数はカウントされる。一方のクォータ管理は、ビジネス要件からリクエスト数の制約を行い、APIコンシューマーに与えられるリクエスト数をSLAとして定めることに役立つ。比較的長い時間軸の中でリクエスト数はカウントされる。
上図は、APIに対してクォータとレート制限を公開している例だ。プランに応じて制約が増減する。クォータ管理はビジネス要件のため最上位プランでは無制限にできるが、レート制限はインフラを保護する必要があるため制約は残る。