502 Bad Gateway(不正なゲートウェイ)

症状

API 呼び出しのレスポンスで、クライアント アプリケーションが HTTP ステータス コード 502、「Bad Gateway」 というメッセージを受け取ります。

HTTP ステータス コード 502 は、クライアントが、リクエストを実際に処理する必要があるバックエンド サーバーから有効なレスポンスを受信していないことを意味します。

エラー メッセージ

クライアント アプリケーションは、次のレスポンス コードを受け取ります。

    HTTP/1.1 502 Bad Gateway
    

さらに、次のエラー メッセージも確認できます。

    {
       "fault": {
          "faultstring": "Unexpected EOF at target",
          "detail": {
               "errorcode": "messaging.adaptors.http.UnexpectedEOFAtTarget"
           }
        }
    }
    

考えられる原因

502 Bad Gateway(不正なゲートウェイ)エラーの一般的な原因の 1 つは、次のような理由により発生する可能性がある [Unexpected EOF] エラーです。

原因 詳細 手順の対象
ターゲット サーバーが正しく構成されていない ターゲット サーバーが、TLS / SSL 接続をサポートするように正しく構成されていません。 Edge Private Cloud と Public Cloud のユーザー
バックエンド サーバーからの EOFException バックエンド サーバーが EOF を突然送信することがあります。 Edge Private Cloud ユーザーのみ

ターゲット サーバーが正しく構成されていない

ターゲット サーバーが、TLS / SSL 接続をサポートするように正しく構成されていません。

診断

Public Cloud ユーザーのみに適用される診断手順

API Monitoring では、問題領域を簡単に切り分けて、エラー、パフォーマンス、レイテンシの問題とその原因(デベロッパー アプリケーション、API プロキシ、バックエンド ターゲット、API プラットフォームなど)を診断できます。

サンプル シナリオの説明に従い、API Monitoring を使用して API での 5xx 問題をトラブルシューティングしてください。たとえば、messaging.adaptors.http.UnexpectedEOFAtTarget エラーの数が特定のしきい値を超えた時点で、アラートを通知するよう設定することもできます。

Private Cloud と Public Cloud のユーザーに適用される診断手順

  1. UI で、影響を受けた API のトレースを有効にします。
  2. 失敗した API リクエストのトレースで次のことが明らかになる場合があります。
    1. ターゲット フロー リクエストが開始されるとすぐに、502 Bad Gateway(不正なゲートウェイ)エラーが表示される。
    2. error.class に messaging.adaptors.http.UnexpectedEOF が表示される。

      この場合、ターゲット サーバーの構成が正しくないことにより問題が発生した可能性が高いと思われます。

  3. Edge 管理 API 呼び出しを使用してターゲット サーバー定義を取得します。
    1. Public Cloud をご利用の場合は、次の API を使用します。
          curl -v https://api.enterprise.apigee.com/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
          
    2. Private Cloud をご利用の場合は、次の API を使用します。
          curl -v http://<management-server-host>:<port #>/v1/organizations/<orgname>/environments/<envname>/targetservers/<targetservername> -u <username>
          

      問題のあるターゲット サーバー定義の例:

          <TargetServer  name="target1">
            <Host>mocktarget.apigee.net</Host>
            <Port>443</Port>
            <IsEnabled>true</IsEnabled>
          </TargetServer >
          
  4. 示されたターゲット サーバー定義は、典型的な構成ミスの 1 つを示す例です。これについては以下で説明します。

    ターゲット サーバー「mocktarget.apigee.net」がポート # 443 で保護された(HTTPS)接続を受け入れるように構成されていると仮定します。しかし、ターゲット サーバー定義を見ると、それが保護された接続用であることを示す他の属性 / フラグはありません。これにより、Edge は特定のターゲット サーバーに送信される API リクエストを HTTP(保護されていない)リクエストとして処理します。したがって、Edge はこのターゲット サーバーとの SSL Handshake プロセスを開始しません。

ターゲット サーバーは 443 で HTTPS(SSL)リクエストのみを受け入れるように構成されているため、このサーバーによって Edge からのリクエストが拒否されるか、接続が閉じられます。結果として、Message Processor で UnexpectedEOFAtTarget エラーが発生します。Message Processor から、クライアントにレスポンスとして「502 Bad Gateway」(不正なゲートウェイ)が送信されます。

解決策

常に、要件に応じてターゲット サーバーが正しく構成されるようにします。

上記の例では、保護された(HTTPS / SSL)ターゲット サーバーにリクエストを行う場合は、「enabled」フラグを true に設定して SSLInfo 属性を含める必要があります。ターゲット エンドポイント定義自体にターゲット サーバーの SSLInfo 属性を追加することは許可されていますが、混乱を避けるために SSLInfo 属性をターゲット サーバー定義の一部として追加することをおすすめします。

  1. バックエンド サービスで一方向の SSL 通信が必要な場合は、次のようにします。
    1. 以下に示すように、「enabled」フラグを true に設定した SSLInfo 属性を含めることによって、ターゲット サーバー定義で TLS / SSL を有効にする必要があります。
          <TargetServer name="mocktarget">
            <Host>mocktarget.apigee.net</Host>
            <Port>443</Port>
            <IsEnabled>true</IsEnabled>
            <SSLInfo>
                <Enabled>true</Enabled>
            </SSLInfo>
          </TargetServer>
          
    2. Edge でターゲット サーバーの証明書を検証する場合は、以下に示すように、トラストストア(ターゲット サーバーの証明書を含む)も含める必要があります。
          <TargetServer  name="mocktarget">
              <IsEnabled>true</IsEnabled>
              <Host>mocktarget.apigee.net</Host>
              <Port>443</Port>
              <SSLInfo>
                  <Ciphers/>
                  <ClientAuthEnabled>false</ClientAuthEnabled>
                  <Enabled>true</Enabled>
                  <IgnoreValidationErrors>false</IgnoreValidationErrors>
                  <Protocols/>
                  <TrustStore>mocktarget-truststore</TrustStore>
              </SSLInfo>
          </TargetServer>
          
  2. バックエンド サービスで双方向の SSL 通信が必要な場合は、次のようにします。
    1. 以下に示すように、SSLInfo 属性に ClientAuthEnabled、Keystore、KeyAlias、Truststore のフラグが適切に設定されている必要があります。
          <TargetServer  name="mocktarget">
      
               <IsEnabled>true</IsEnabled>
      
               <Host>www.example.com</Host>
      
               <Port>443</Port>
      
               <SSLInfo>
      
                   <Ciphers/>
      
                   <ClientAuthEnabled>true</ClientAuthEnabled>
      
                   <Enabled>true</Enabled>
      
                   <IgnoreValidationErrors>false</IgnoreValidationErrors>
      
                   <KeyAlias>keystore-alias</KeyAlias>
      
                   <KeyStore>keystore-name</KeyStore>
      
                   <Protocols/>
      
                   <TrustStore>truststore-name</TrustStore>
      
               </SSLInfo>
      
            </TargetServer >
          

リファレンス

バックエンド サーバー間の負荷分散

バックエンド サーバーからの EOFException

バックエンド サーバーが EOF(ファイルの終わり)を突然送信することがあります。

診断

Public Cloud ユーザーのみに適用される診断手順

API Monitoring では、問題領域を簡単に切り分けて、エラー、パフォーマンス、レイテンシの問題とその原因(デベロッパー アプリケーション、API プロキシ、バックエンド ターゲット、API プラットフォームなど)を診断できます。

API Monitoring を使用して API での 5xx 問題をトラブルシューティングする方法を説明するサンプル シナリオに従ってください。たとえば、messaging.adaptors.http.UnexpectedEOFAtTarget エラーの数が特定のしきい値を超えた時点で、アラートを通知するよう設定することもできます。

Private Cloud ユーザーのみに適用される診断手順

  1. Message Processor のログ(/opt/apigee/var/log/edge-message-processor/logs/system.log)を確認し、特定の API に対して「eof unexpected」が発生したかどうかを検索するか、API リクエストに一意の messageid があるかどうかを検索してから、それを検索できます。

    Message Processor ログの例外スタック トレースの例

        "message": "org:myorg env:test api:api-v1 rev:10 messageid:rrt-1-14707-63403485-19 NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context$3.onException() : SSLClientChannel[C:193.35.250.192:8443 Remote host:0.0.0.0:50100]@459069 useCount=6 bytesRead=0 bytesWritten=755 age=40107ms lastIO=12832ms .onExceptionRead exception: {}
        java.io.EOFException: eof unexpected
        at com.apigee.nio.channels.PatternInputChannel.doRead(PatternInputChannel.java:45) ~[nio-1.0.0.jar:na]
        at com.apigee.nio.channels.InputChannel.read(InputChannel.java:103) ~[nio-1.0.0.jar:na]
        at com.apigee.protocol.http.io.MessageReader.onRead(MessageReader.java:79) ~[http-1.0.0.jar:na]
        at com.apigee.nio.channels.DefaultNIOSupport$DefaultIOChannelHandler.onIO(NIOSupport.java:51) [nio-1.0.0.jar:na]
        at com.apigee.nio.handlers.NIOThread.run(NIOThread.java:123) [nio-1.0.0.jar:na]"
        

    上の例では、「java.io.EOFException: eof unexpected」のエラーが、Message Processor がバックエンド サーバーからのレスポンスを読み取ろうとしているときに発生しました。この例外は、ファイルの終わり(EOF)か、予期せずストリームの終わりに達したことを示しています。

    つまり、Message Processor は、API リクエストをバックエンド サーバーに送信し、レスポンスを待機していたか、読み取っていました。しかし、バックエンド サーバーは、Message Processor がレスポンスを受け取る前、または完全なレスポンスを読み取るまでに、突然接続を終了しました。

  2. バックエンド サーバーのログを確認し、バックエンド サーバーの突然の接続終了を引き起こした可能性のあるエラーや情報がないかどうかを確認します。エラーや情報が見つかった場合は、「解決策」の手順に進み、バックエンド サーバーで問題を適切に修正します。
  3. バックエンド サーバーでエラーや情報が見つからない場合は、Message Processor で tcpdump の出力を収集します。
    1. バックエンド サーバー ホストに単一の IP アドレスがある場合は、次のコマンドを使用します。
          tcpdump -i any -s 0 host <IP address> -w <File name>
          
    2. バックエンド サーバー ホストに複数の IP アドレスがある場合は、次のコマンドを使用します。
          tcpdump -i any -s 0 host <Hostname> -w <File name>
          

      通常、このエラーは、Message Processor がリクエストをバックエンド サーバーに送信するとすぐにバックエンド サーバーが [FIN,ACK] で応答することが原因で発生します。

  4. 以下の tcpdump の例を考えてみましょう。

    502 Bad Gateway(不正なゲートウェイ)エラー(UnexpectedEOFAtTarget)が発生した場合に実行された tcpdump の例

  5. TCPDump の出力から、次の一連のイベントに注目します。
    1. Message Processor が API リクエストをバックエンド サーバーに送信します。
    2. バックエンド サーバーがすぐに [FIN,ACK] で応答します。
    3. これに続いて、Message Processor が [FIN,ACK] でバックエンド サーバーに応答します。
    4. 最終的に双方から [ACK] と [RST] で接続が閉じられます。
    5. バックエンド サーバーは [FIN,ACK] を送信するため、Message Processor で「java.io.EOFException: eof unexpected」の例外が発生します。
  6. これは、バックエンド サーバーにネットワークの問題がある場合に発生します。この問題をさらに調査するために、ネットワーク運用チームに依頼してください。

解決策

バックエンド サーバーの問題を適切に修正します。

問題が引き続き発生し、502 Bad Gateway(不正なゲートウェイ)のエラーをトラブルシューティングするサポートが必要な場合、またはこれが Edge 内の問題であることが疑われる場合は、Apigee サポートにお問い合わせください。