アンチパターン: エラー レスポンスのキャッシュ

キャッシュ保存とは、後から参照できるように、キャッシュと呼ばれる一時的なストレージ領域にデータを保存するプロセスです。データをキャッシュすることで以下が可能になり、パフォーマンス上の大きな利点が得られます。

  • データを高速に取得
  • データを何度も繰り返し生成する必要がないため、処理時間を短縮
  • API リクエストがバックエンド サーバーに送られるのを阻止し、バックエンド サーバーのオーバーヘッドを低減
  • システムおよびアプリケーション リソースの使用率を効率化
  • API の応答時間を改善

あまり変更されることがない、頻繁にアクセスする必要のあるデータであれば、キャッシュを使用して保存しておくことを強く推奨します。

Apigee Edge では、ランタイム時にデータをキャッシュに保存することで、データが存続して高速な取得が可能になります。キャッシュ機能を使用するには、PopulateCache ポリシーLookupCache ポリシーInvalidateCache ポリシーResponseCache ポリシーを使用します。

このセクションでは、Response Cache ポリシーについて説明します。Apigee Edge プラットフォームの Response Cache ポリシーを使用すると、バックエンド サーバーからのレスポンスをキャッシュに保存できます。クライアント アプリケーションが同じバックエンド リソースを何度もリクエストし、そのリソースが一定期間ごとに更新されるような場合は、Response Cache ポリシーを使ってこれらのレスポンスをキャッシュに保存できます。Response Cache ポリシーを使用すると、キャッシュに保存したレスポンスが返されるので、リクエストがバックエンド サーバーに不必要に転送されることを回避できます。

Response Cache ポリシーの機能は、次のとおりです。

  • バックエンドに到達するリクエストの数を低減
  • ネットワーク帯域幅を低減
  • API のパフォーマンスと応答時間を向上

アンチパターン

ResponseCache ポリシーを使用すると、デフォルトでは、どのステータス コードの HTTP レスポンスもキャッシュに保存されます。つまり、成功レスポンスもエラー レスポンスもキャッシュされます。

次に、デフォルト構成の Response Cache ポリシーの例を示します。

<!-- /antipatterns/examples/1-1.xml -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResponseCache async="false" continueOnError="false" enabled="true" name="TargetServerResponseCache">
  <DisplayName>TargetServer ResponseCache</DisplayName>
  <CacheKey>
    <Key Fragment ref="request.uri" /></CacheKey>
    <Scope>Exclusive</Scope>
    <ExpirySettings>
      <TimeoutInSec ref="flow.variable.here">600</TimeoutInSec>
    </ExpirySettings>
  <CacheResource>targetCache</CacheResource>
</ResponseCache>

Response Cache ポリシーをデフォルト構成で使用すると、エラー レスポンスもキャッシュに保存されます。しかし、その悪影響についてよく考えずにエラー レスポンスをキャッシュに保存することはおすすめできません。これには、以下のような理由があります。

  • シナリオ 1: 障害発生が一時的なもので、どれだけ続くか不明な場合は、エラー レスポンスをキャッシュに保存しておくと、問題が解決した後も引き続きエラー レスポンスが送信されてしまう可能性があります。

    または

  • シナリオ 2: 障害の続く時間が事前にわかっている場合は、問題が解決した時点でレスポンスのキャッシュ保存を回避するように、コードを修正する必要があります。

次に、この 2 つのシナリオについて詳しく説明します。

シナリオ 1: バックエンドまたはリソースに関連する一時的な障害

バックエンド サーバー障害が、以下のいずれかの理由で発生したとします。

  • 一時的なネットワーク障害
  • バックエンド サーバーが極度のビジー状態で、一時的な期間、リクエストに応答できない
  • リクエストされたバックエンド リソースが一時的に除去されているか、または一時的に使用できない
  • 処理が一時的に集中しているため、バックエンド サーバーのレスポンスが低速化している、など

上記のどの場合も、障害がいつまで続くかは不明であり、再び成功レスポンスを受け取るようになる可能性があります。エラー レスポンスをキャッシュに保存すると、バックエンド サーバーの問題が解決した後も、エラー レスポンスがユーザーに送信され続ける可能性があります。

シナリオ 2: 長期的な、または一定期間のバックエンド / リソース障害

バックエンド障害が一定時間発生することが事前にわかっているとします。たとえば、次のことが事前にわかっているような場合です。

  • 特定のバックエンド リソースが 1 時間だけ使用できない。

    または

  • 急なサイト障害、スケーリングに関する問題、メンテナンス、アップグレードなどが原因で、24 時間にわたりバックエンド サーバーが除去されるか、または使用できない。

このような情報がわかっていれば、必要な期間以上にエラー レスポンスがキャッシュされないように、キャッシュの適切な有効期限を Response Cache ポリシーで設定できます。しかし、バックエンド サーバーまたはリソースが再度使用可能になった時点で、エラー レスポンスが今後もキャッシュされないように、ポリシーを修正しなければなりません。バックエンド サーバーで一時的な、または 1 回限りの障害が発生した場合にレスポンスをキャッシュに保存し続けると、結局は上記の「シナリオ 1」で説明した問題が発生することになります。

影響

  • エラー レスポンスをキャッシュに保存すると、バックエンド サーバーの問題が解決した後でもエラー レスポンスが送信され続ける可能性があります。
  • バックエンド サーバーからのエラー レスポンスをキャッシュに保存していることが原因だとわからず、ユーザーは問題のトラブルシューティングに多大な労力を費やすことになりかねません。

ベスト プラクティス

  • エラー レスポンスをレスポンス キャッシュに保存しないようにします。エラー レスポンスがキャッシュに保存されないようにするには、ResponseCache ポリシー<ExcludeErrorResponse> 要素を true に設定します。以下のコード スニペットをご覧ください。このように構成すると、デフォルトの成功コード 200~205 のレスポンスだけがキャッシュされます(成功コードが変更されない限り)。
    <!-- /antipatterns/examples/1-2.xml -->
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <ResponseCache async="false" continueOnError="false" enabled="true" name="TargetServerResponseCache">
      <DisplayName>TargetServerResponseCache</DisplayName>
      <CacheKey>
        <KeyFragment ref="request.uri" />
      </CacheKey>
      <Scope>Exclusive</Scope>
      <ExpirySettings>
        <TimeoutinSec ref="flow.variable.here">600</TimeoutinSec>
      </ExpirySettings>
      <CacheResource>targetCache</CacheResource>
      <ExcludeErrorResponse>true</ExcludeErrorResponse>
    </ResponseCache>
    
  • なんらかの理由でエラー レスポンスをキャッシュに保存しなければならない場合は、障害を監視する最大時間または正確な時間を設定します(可能であれば)。
    • 必要な障害監視時間を過ぎてもエラー レスポンスがキャッシュに保存されないように、キャッシュの適切な有効期限を設定します。
    • <ExcludeErrorResponse> 要素を含めずに ResponseCache ポリシーを使用して、エラー レスポンスをキャッシュに保存します。

    バックエンド サーバーの障害が短時間または一時的なものでないことが確実にわかっている場合にのみ、この処理を行ってください。

  • Apigee では、バックエンド サーバーからの 5xx レスポンスをキャッシュすることはおすすめしません。