アンチパターン: 単一ターゲット サーバーの負荷分散において MaxFailures の値をゼロ以外に設定する

TargetEndpoint 構成は、Apigee Edge がバックエンド サービスまたは API に接続する方法を定義します。こうしてバックエンド サービスにリクエストが送信され、バックエンド サービスからのレスポンスが受信されます。バックエンド サービスは、HTTP / HTTPS サーバー、NodeJS、Hosted Target のいずれかです。

TargetEndpoint では、バックエンド サービスを次のいずれかの方法で起動できます。

  • HTTP または HTTPS サーバーへのダイレクト URL
  • Edge がホストする Node.js スクリプトに対する ScriptTarget
  • Hosted Target 環境にデプロイされた NodeJS に対する HostedTarget
  • TargetServer 構成

同様に、Service Callout ポリシーを使用して、任意の外部サービスを API プロキシフローから呼び出すこともできます。このポリシーを使用すると、ポリシー自体で直接、または TargetServer 構成を使用して、HTTP / HTTPS ターゲット URL を定義できます。

TargetServer 構成

TargetServer 構成は、実際のエンドポイント URL を TargetEndpoint 構成から分離したり、Service Callout ポリシー内で分離したりします。TargetEndpoint では、TargetServer は URL ではなく名前で参照されます。TargetServer 構成には、バックエンド サービスのホスト名やポート番号、その他の詳細情報が格納されます。

次に、TargetServer 構成の例を示します。

<TargetServer name="target1">
  <Host>www.mybackendservice.com</Host>
  <Port>80</Port>
  <IsEnabled>true</IsEnabled>
</TargetServer>

TargetServer を使用することで、環境ごとに異なる構成を用意できます。TargetEndpoint ポリシーや Service Callout ポリシーを構成するには、LoadBalancer を使って 1 つまたは複数の名前付き TargetServer を使用できます。負荷分散が組み込みでサポートされるので、構成されたバックエンド サーバー インスタンス間で API 可用性とフェイルオーバーが強化されます。

次に、TargetServer を使用した TargetEndpoint 構成の例を示します。

<TargetEndpoint name="default">
    <HTTPTargetConnection>>
      <LoadBalancer>
        <Server name="target1"/>
      <Server name="target2"/>
      </LoadBalancer>
    </HTTPTargetConnection>
</TargetEndpoint>

MaxFailures

MaxFailures 構成は、ターゲット サーバーへのリクエストの最大失敗回数を指定します。この回数に達したターゲット サーバーは停止状態としてマークされ、以降のすべてのリクエストに関するローテーションから除外されます。

次に、MaxFailures を指定した構成の例を示します。

<TargetEndpoint name="default">
    <HTTPTargetConnection>
      <LoadBalancer>
        <Server name="target1"/>
       <Server name="target2"/>
       <MaxFailures>5</MaxFailures>
      </LoadBalancer>
    </HTTPTargetConnection>
</TargetEndpoint>

この例では、「target1」へのリクエストが連続して 5 回失敗すると、「target1」はローテーションから除外され、以降のすべてのリクエストは「target2」のみに送られます。

アンチパターン

TargetEndpoint の LoadBalancer で TargetServer を 1 つだけ指定する構成、または Service Callout ポリシーの MaxFailures を 0 以外の値に設定する構成は、悪影響が生じる可能性があり、おすすめできません。

「target1」という名前の 1 つの TargetServer だけが存在し、MaxFailures が 5(非ゼロ値)に設定されている次の構成例について考えてみます。

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <MaxFailures>5</MaxFailures>
      </LoadBalancer>
  </HTTPTargetConnection>

TargetServer「target1」へのリクエストが 5 回(MaxFailures に指定した数)失敗すると、TargetServer はローテーションから除外されます。しかし、フェイルオーバー先となる別の TargetServer が存在しないため、この構成の API プロキシに対する以降のリクエストはすべて、503 Service Unavailable エラーによって失敗します。

TargetServer「target1」が正常な状態に戻り、正常なレスポンスを返せるようになっても、この API プロキシへのリクエストには引き続き 503 エラーが返されます。その理由は、TargetServer が再稼働するようになっても、Edge がこの TargetServer を自動的にローテーションに戻さないためです。この問題を解決するには、TargetServer が Edge で再びローテーションに戻されるように API プロキシを再デプロイする必要があります

Service Callout ポリシーでこれと同じ構成を使用した場合は、TargetServer「target1」への API リクエストが 5 回失敗した後、リクエストに対して 500 エラーが返されます。

影響

TargetEndpoint の LoadBalancer 構成に TargetServer を 1 つしか指定しない場合、または Service Callout ポリシーの MaxFailures を 0 以外の値に設定した場合は、以下の影響が生じます。

  • API プロキシを再デプロイするまでは、(リクエストの失敗回数が MaxFailures に指定した数を超えた時点以降)API リクエストが失敗し、503 / 500 エラーが返され続けます。
  • 問題の原因の診断が難しく、時間がかかる可能性があるため(このアンチパターンについての予備知識がない場合)、停止状態が長引きます。

ベスト プラクティス

  1. 高可用性を実現する目的で、LoadBalancer 構成に複数の TargetServer を設定します。
  2. MaxFailures を 0 以外の値に設定する場合は、常にヘルスモニターを定義します。失敗回数が MaxFailures に指定した数に達すると、ターゲット サーバーはローテーションから除外されます。HealthMonitor を設置することで、ターゲット サーバーが再稼働した時点ですぐにローテーションに戻されるので、プロキシを再デプロイする必要がありません

    ターゲット サーバーへの接続用に Edge で使われるものと同じポート番号でヘルスチェックを確実に実行するには、<TCPMonitor> の子要素 <Port> を省略することをおすすめします(TargetServer ポートと異なる番号でない限り)。デフォルトでは、<Port> は TargetServer ポートと同じです。

    HealthMonitor を使用する構成の例:

    <TargetEndpoint name="default">
      <HTTPTargetConnection>
        <LoadBalancer>
          <Algorithm>RoundRobin</Algorithm>
          <Server name="target1" />
          <Server name="target2" />
          <MaxFailures>5</MaxFailures>
        </LoadBalancer>
        <Path>/test</Path>
        <HealthMonitor>
          <IsEnabled>true</IsEnabled>
          <IntervalInSec>5</IntervalInSec>
          <TCPMonitor>
            <ConnectTimeoutInSec>10</ConnectTimeoutInSec>
          </TCPMonitor>
        </HealthMonitor>
      </HTTPTargetConnection>
    </TargetEndpoint>
    
  3. なんらかの制限によって TargetServer を 1 つしか設置できない状況で、HealthMonitor も使用しない場合は、LoadBalancer 構成内で MaxFailures を指定しないでください。

    MaxFailures のデフォルト値は 0 です。 この値の場合、Edge はリクエストが送られるたびにターゲットへの接続を試み、ターゲット サーバーをローテーションから決して除外しません。

関連情報