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

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

  • データを高速に取得
  • データを何度も繰り返し生成する必要がないため、処理時間を短縮
  • 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 レスポンスをキャッシュすることはおすすめしません。