症状
クライアント アプリケーションが API 呼び出しに対するレスポンスとして、HTTP ステータス コード 504 とメッセージ「Gateway Timeout」を受け取ります。
HTTP ステータス コード - 504 Gateway Timeout のエラーは、クライアントが、API の実行中に Edge Gateway またはバックエンド サーバーからタイムリーなレスポンスを受信しなかったことを示します。
エラー メッセージ
クライアント アプリケーションは、次のレスポンス コードを受け取ります。
HTTP/1.1 504 Gateway Timeout
場合によっては、次のエラー メッセージが表示されることもあります。
{ "fault": { "faultstring": "Gateway Timeout", "detail": { "errorcode": "messaging.adaptors.http.flow.GatewayTimeout" } } }
ゲートウェイ タイムアウトの原因
Edge プラットフォームを経由する API リクエストの一般的なパスは、下の図に示すように、クライアント -> Router -> Message Processor -> バックエンド サーバーです。
Edge プラットフォーム内のクライアント アプリケーション、Router、Message Processor は、適切なタイムアウト値で設定されます。Edge プラットフォームでは、タイムアウト値に基づいて、すべての API リクエストに対して特定の期間内にレスポンスが送信されることを前提としています。指定した時間内にレスポンスが得られない場合は、504 Gateway Timeout エラーが返されます。
次の表に、Edge でタイムアウトが発生する可能性のある状況の詳細を示します。
タイムアウトの発生 | 詳細 |
Message Processor でのタイムアウトの発生 |
|
Router でのタイムアウトの発生 |
|
クライアント アプリケーションでのタイムアウトの発生 |
|
考えられる原因
Edge での、504 Gateway Timeout エラーの一般的な原因は次のとおりです。
原因 | 詳細 | 手順の対象 |
バックエンド サーバーが遅い | 負荷が高いかパフォーマンスが低いことが原因で、API リクエストを処理しているバックエンド サーバーが遅すぎます。 | Public Cloud と Private Cloud のユーザー |
Edge による API プロキシの処理が遅い | 負荷が高いかパフォーマンスが低いことが原因で、Edge が API リクエストを処理するのに時間がかかります。 |
バックエンド サーバーが遅い
バックエンド サーバーが非常に遅い、または API リクエストを処理するのに時間がかかる場合は、504 Gateway Timeout エラーが発生します。上記のセクションで説明したように、タイムアウトは次のいずれかのシナリオで発生します。
- バックエンド サーバーが応答する前に Message Processor がタイムアウトする。
- Message Processor / バックエンド サーバーが応答する前に Router がタイムアウトする。
- Router / Message Processor / バックエンド サーバーが応答する前にクライアント アプリケーションがタイムアウトする。
以下のセクションでは、これらのシナリオごとに問題を診断して解決する方法について説明します。
シナリオ 1 - バックエンド サーバーが応答する前に Message Processor がタイムアウトする
診断
次の手順を使用すると、バックエンド サーバーが遅いことが原因で 504 Gateway Timeout エラーが発生したかどうかを診断できます。
手順 1: トレースを使用する
問題が引き続き発生する場合(504 のエラーが引き続き発生する場合)は、以下の手順に従ってください。
- Edge UI で影響を受ける API をトレースします。エラーが発生するのを待つか、API 呼び出しがある場合は、API 呼び出しを行い、504 Gateway Timeout エラーを再現します。
- エラーが発生したら、レスポンス コードが 504 である特定のリクエストを調べます。
- 各フェーズの経過時間を確認し、ほとんどの時間が費やされているフェーズをメモします。
- 次のフェーズのいずれかの直後に最も長い経過時間を持つ「エラー」が発生した場合は、バックエンド サーバーが遅いか、リクエストを処理するのに時間がかかることを示します。
- 「ターゲット サーバーに送信されたリクエスト」
- Service Callout ポリシー
次に、バックエンド サーバーが 55 秒経過しても応答しなかったことで 504 Gateway Timeout エラーが発生したことを示すトレースの例を示します。
上記のトレースでは、バックエンド サーバーが応答しないため、55,002 ミリ秒後に Message Processor がタイムアウトします。
手順 2: Message Processor のログを使用する
- Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log
)を確認します。 - 特定の時間の特定の API プロキシ リクエストに「Gateway Timeout」と「onTimeoutRead」のエラーが見つかった場合、Message Processor がタイムアウトしたことを示します。
Gateway Timeout エラーを表示している Message Processor のログの例
2015-09-29 20:16:54,340 org:myorg env:staging api:profiles rev:13 NIOThread@1 ERROR ADAPTORS.HTTP.FLOW - AbstractResponseListener.onException() : AbstractResponseListener.onError(HTTPResponse@4d898cf1, Gateway Timeout) 2015-09-29 20:16:57,361 org:myorg env:staging api:profileNewsletters rev:8 NIOThread@0 ERROR HTTP.CLIENT - HTTPClient$Context$3.onTimeout() : SSLClientChannel[C:XX.XX.XX.XX:443 Remote host:192.168.38.54:38302]@120171 useCount=2 bytesRead=0 bytesWritten=824 age=55458ms lastIO=55000ms .onTimeoutRead
上記の Message Processor のログでは、IP アドレス XX.XX.XX.XX で示されたバックエンド サーバーが 55 秒経過しても応答しなかったことがわかります(lastIO=55000ms)。結果として、Message Processor がタイムアウトし、504 Gateway Timeout エラーが送信されました。
要確認: Message Processor でのタイムアウトの制御方法
- Message Processor でのタイムアウトの制御方法: Message Processor は、通常、プロパティ「HTTPTransport.io.timeout.millis」を使用して、55 秒のデフォルトのタイムアウト値で設定されます。このタイムアウト値は、この Message Processor によって処理される組織に属するすべての API プロキシに適用されます。
- バックエンド サーバーが 55 秒以内に応答しない場合、Message Processor はタイムアウトし、504 Gateway Timeout エラーをクライアントに送信します。
- Message Processor で指定されたタイムアウト値は、API プロキシ内で指定されたプロパティ「io.timeout.millis」でオーバーライドできます。このタイムアウト値は、上記のプロパティが指定されている特定の API プロキシに適用されます。たとえば、io.timeout.millis が API プロキシ内で 10 秒に設定されている場合、この特定の API プロキシには 10 秒のタイムアウト値が使用されます。
- この特定の API プロキシでは、バックエンド サーバーが 10 秒以内に応答しない場合、Message Processor はタイムアウトし、504 Gateway Timeout エラーをクライアントに送信します。
- Message Processor でのタイムアウトの制御方法: Message Processor は、通常、プロパティ「HTTPTransport.io.timeout.millis」を使用して、55 秒のデフォルトのタイムアウト値で設定されます。このタイムアウト値は、この Message Processor によって処理される組織に属するすべての API プロキシに適用されます。
解決策
- バックエンド サーバーが 55 秒以上かかる理由を確認し、応答時間が短縮されるように修正または最適化できるかどうかを確認します。
- バックエンド サーバーを修正 / 最適化できない場合、または構成されたタイムアウトよりも長い時間がバックエンド サーバーでかかることがわかっている場合は、Router と Message Processor のタイムアウト値を適切な値に増やします。この手順を実施できるのは Private Cloud ユーザーのみです。Public Cloud を使用している場合は、Apigee サポートにお問い合わせください。
シナリオ 2 - Message Processor / バックエンド サーバーが応答する前に Router がタイムアウトする
Message Processor / バックエンド サーバーが応答する前に Router がタイムアウトすると、504 Gateway Timeout エラーが発生する可能性があります。これは、次のいずれかの状況で発生します。
- Router で設定されたタイムアウト値は、Message Processor で設定されたタイムアウト値よりも短くなっています。たとえば、Router のタイムアウトが 50 秒で、Message Processor のタイムアウトが 55 秒であるとします。
Router のタイムアウト Message Processor のタイムアウト 50 秒 55 秒 - Message Processor のタイムアウト値は、API プロキシのターゲット エンドポイント構成内で設定された「io.timeout.millis」プロパティを使用して、より高いタイムアウト値でオーバーライドされます。
たとえば、次のタイムアウト値が設定されているとします。
Router のタイムアウト Message Processor のタイムアウト API プロキシ内のタイムアウト 57 秒 55 秒 120 秒 ただし、API プロキシでは、io.timeout.millis が 120 秒に設定されています。
<HTTPTargetConnection> <Properties> <Property name="io.timeout.millis">120000</Property> </Properties> <URL>http://www.apigee.com</URL> </HTTPTargetConnection>
この場合、Message Processor のタイムアウト値(55 秒)が Router のタイムアウト値(57 秒)よりも小さくても、Message Processor は 55 秒後にタイムアウトしません。これは、Message Processor の 55 秒のタイムアウト値が、API プロキシ内で設定された 120 秒の値によってオーバーライドされるためです。したがって、この特定の API プロキシの Message Processor のタイムアウト値は 120 秒になります。
Router は、API プロキシ内で設定された 120 秒と比較してタイムアウト値が低い(57 秒)ため、バックエンド サーバーが 57 秒経過しても応答しない場合、タイムアウトします。
診断
- Nginx のアクセスログ(
/opt/apigee/var/log/edge-router/nginx/<org>~<env>.<port#>_access_log
)を確認します。 - Router が Message Processor の前にタイムアウトした場合、特定の API リクエストの Nginx アクセスログに 504 のステータスが表示され、Message Processor のメッセージ ID は「-」に設定されます。これは、Router が、Router に設定されたタイムアウト期間内に Message Processor からレスポンスを受け取らなかったためです。
Router のタイムアウトによる 504 を示す Nginx のログエントリの例
- 上記の例では、Nginx の 504 のステータス、Message Processor からのメッセージ ID が「-」であること、合計経過時間が 57.001 秒であることがわかります。これは、Router が 57.001 秒後にタイムアウトし、Message Processor からレスポンスを受け取らなかったためです。
- この場合、Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log).
に「Broken Pipe」の例外が表示されます。2017-06-09 00:00:25,886 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-mp01-18869-23151-1 NIOThread@1 INFO HTTP.SERVICE - ExceptionHandler.handleException() : Exception java.io.IOException: Broken pipe occurred while writing to channel ClientOutputChannel(ClientChannel[A:XX.XX.XX.XX:8998 Remote host:YY.YY.YY.YY:51400]@23751 useCount=1 bytesRead=0 bytesWritten=486 age=330465ms lastIO=0ms ) 2017-06-09 00:00:25,887 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-mp01-18869-23151-1 NIOThread@1 INFO HTTP.SERVICE - ExceptionHandler.handleException() : Exception trace: java.io.IOException: Broken pipe at com.apigee.nio.channels.ClientOutputChannel.writePending(ClientOutputChannel.java:51) ~[nio-1.0.0.jar:na] at com.apigee.nio.channels.OutputChannel.onWrite(OutputChannel.java:116) ~[nio-1.0.0.jar:na] at com.apigee.nio.channels.OutputChannel.write(OutputChannel.java:81) ~[nio-1.0.0.jar:na] … <snipped>
Router がタイムアウトすると、Message Processor との接続が閉じられるため、このエラーが表示されます。Message Processor は、処理を完了すると、レスポンスを Router に書き込もうとします。Router への接続はすでに閉じられているため、Message Processor で Broken Pipe 例外が発生します。
この例外は、前述の状況下で発生すると予想されます。したがって、504 Gateway Timeout エラーの実際の原因は、依然としてバックエンド サーバーの応答に時間がかかることであり、その問題に対処する必要があります。
解決策
- カスタム バックエンド サーバーの場合は、次の手順に従います。
- バックエンド サーバーの応答に時間がかかる理由を確認し、応答時間が短縮されるように修正または最適化できるかどうかを確認します。
- バックエンド サーバーを修正 / 最適化できない場合、またはバックエンド サーバーで時間がかかることがわかっている場合は、Router と Message Processor のタイムアウト値を増やします。
提案: 次の順序で、各種コンポーネントのタイムアウト値を設定します。
クライアントのタイムアウト > Router のタイムアウト > Message Processor のタイムアウト > API プロキシ内のタイムアウト
- NodeJS バックエンド サーバーの場合は、次の手順に従います。
- NodeJS コードで他のバックエンド サーバーへの呼び出しが行われているかどうかと、レスポンスを返されるまでに時間がかかるかどうかを確認します。バックエンド サーバーで時間がかかる理由を確認し、問題を適切に修正します。
- Message Processor で CPU またはメモリの使用率が高いかどうかを確認します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
<JAVA_HOME>/bin/jstack -l <pid> > <filename>
- Message Processor のメモリ使用率が高い場合は、次のコマンドを使用してヒープダンプを生成します。
sudo -u apigee <JAVA_HOME>/bin/jmap -dump:live,format=b,file=<filename> <pid>
- 次のコマンドを使用して Message Processor を再起動します。これにより、CPU とメモリの使用率が下がります。
/opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
- API 呼び出しをモニタリングし、まだ問題が存在するかどうかを確認します。
- CPU / メモリの使用率が高い原因を調査できるように、Apigee サポートにスレッドダンプ、ヒープダンプ、Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log)
を提供します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
要確認: Message Processor での NodeJS バックエンド サーバーに対するタイムアウトの制御方法
|
シナリオ 3 - Router / Message Processor / バックエンド サーバーが応答する前にクライアント アプリケーションがタイムアウトする
バックエンド サーバーが応答する前にクライアント アプリケーションがタイムアウトすると、504 Gateway Timeout エラーが発生する可能性があります。この状況は、次の場合に発生します。
- クライアント アプリケーションで設定されたタイムアウト値は、Router と Message Processor で設定されたタイムアウト値よりも低くなっています。
たとえば、次のタイムアウト値が設定されているとします。
クライアントのタイムアウト Router のタイムアウト Message Processor のタイムアウト 50 秒 57 秒 55 秒 この場合、Edge 経由で API リクエストのレスポンスを受け取るために利用可能な合計時間は 50 秒以下です。これには、API リクエストの作成から Edge(Router、Message Processor)によるリクエスト処理、バックエンド サーバーへのリクエスト送信(該当する場合)、バックエンドでのリクエスト処理とレスポンス送信、Edge でのレスポンス処理、最後にクライアントへの返送にかかるまでの時間が含まれます。
Router が 50 秒以内にクライアントに応答しない場合、クライアントはタイムアウトして Router との接続を閉じます。クライアントはレスポンス コード 504 を受け取ります。
これにより、Nginx で、クライアントが接続を閉じたことを示す 499 のステータス コードが設定されます。
診断
- クライアント アプリケーションが Router からのレスポンスを受け取る前にタイムアウトすると、Router との接続が閉じられます。この状況では、特定の API リクエストの Nginx アクセスログにステータス コード 499 が表示されます。
ステータス コード 499 を示す Nginx のログエントリの例
- 上記の例で、Nginx の 499 のステータスと、合計経過時間が 50.001 秒であることに注目してください。これは、クライアントが 50.001 秒後にタイムアウトしたことを示します。
- この場合、Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log).
に「Broken Pipe」の例外が表示されます。
2017-06-09 00:00:25,886 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-1-11193-11467656-1 NIOThread@1 INFO HTTP.SERVICE - ExceptionHandler.handleException() : Exception java.io.IOException: Broken pipe occurred while writing to channel ClientOutputChannel(ClientChannel[A:XX.XX.XX.XX:8998 Remote host:YY.YY.YY.YY:51400]@23751 useCount=1 bytesRead=0 bytesWritten=486 age=330465ms lastIO=0ms ) 2017-06-09 00:00:25,887 org:myorg env:test api:myapi-v1 rev:23 messageid:rrt-1-11193-11467656-1 NIOThread@1 INFO HTTP.SERVICE - ExceptionHandler.handleException() : Exception trace: java.io.IOException: Broken pipe at com.apigee.nio.channels.ClientOutputChannel.writePending(ClientOutputChannel.java:51) ~[nio-1.0.0.jar:na] at com.apigee.nio.channels.OutputChannel.onWrite(OutputChannel.java:116) ~[nio-1.0.0.jar:na] at com.apigee.nio.channels.OutputChannel.write(OutputChannel.java:81) ~[nio-1.0.0.jar:na] … <snipped>
- Router がタイムアウトすると、Message Processor との接続が閉じられます。Message Processor は、処理を完了すると、レスポンスを Router に書き込もうとします。Router への接続はすでに閉じられているため、Message Processor で Broken Pipe 例外が発生します。
- この例外は、前述の状況下で想定されます。したがって、504 Gateway Timeout エラーの実際の原因は、依然としてバックエンド サーバーの応答に時間がかかることであり、その問題に対処する必要があります。
解決策
- カスタム バックエンド サーバーの場合は、次の手順に従います。
- バックエンド サーバーが 57 秒以上かかる理由を確認し、応答時間が短縮されるように修正または最適化できるかどうかを確認します。
- バックエンド サーバーを修正 / 最適化できない場合、またはバックエンド サーバーで時間がかかることがわかっている場合は、Router と Message Processor のタイムアウト値を増やします。
提案: 次の順序で、各種コンポーネントのタイムアウト値を設定します。
クライアントのタイムアウト > Router のタイムアウト > Message Processor のタイムアウト > API プロキシ内のタイムアウト
- NodeJS バックエンドの場合は、次の手順に従います。
- NodeJS コードで他のバックエンド サーバーへの呼び出しが行われているかどうかと、応答に時間がかかるかどうかを確認します。それらのバックエンド サーバーで時間がかかる理由を確認します。
- Message Processor で CPU またはメモリの使用率が高いかどうかを確認します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
<JAVA_HOME>/bin/jstack -l <pid> > <filename>
- Message Processor のメモリ使用率が高い場合は、次のコマンドを使用してヒープダンプを生成します。
sudo -u apigee <JAVA_HOME>/bin/jmap -dump:live,format=b,file=<filename> <pid>
- 次のコマンドを使用して Message Processor を再起動します。これにより、CPU とメモリの使用率が下がります。
/opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
- API 呼び出しをモニタリングし、まだ問題が存在するかどうかを確認します。
- CPU / メモリの使用率が高い原因を調査できるように、Apigee サポートにスレッドダンプ、ヒープダンプ、Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log)
を提供します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
Router と Message Processor のタイムアウト値を増やす
要件に応じて、Router と Message Processor で設定するタイムアウト値を慎重に選択します。独断で大きいタイムアウト値を設定しないでください。不明な点がある場合は Apigee サポートにご連絡ください。
Router
chown apigee:apigee /opt/apigee/customer/application/router.properties
- Router マシンに
/opt/apigee/customer/application/router.properties
ファイルがまだ存在しない場合は作成します。 - このファイルに次の行を追加します。
conf_load_balancing_load.balancing.driver.proxy.read.timeout=<time in seconds>
たとえば、タイムアウト値を 120 秒に設定する場合は、次のように設定します。
conf_load_balancing_load.balancing.driver.proxy.read.timeout=120
- このファイルが apigee によって所有されていることを確認します。
- Router を再起動します。
/opt/apigee/apigee-service/bin/apigee-service edge-router restart
- 複数の Router がある場合は、すべての Router で上記の手順を繰り返します。
Message Processor
- Message Processor マシン上に
/opt/apigee/customer/application/message-processor.properties
ファイルがまだ存在しない場合は作成します。 - このファイルに次の行を追加します。
conf_http_HTTPTransport.io.timeout.millis=<time in milliseconds>
たとえば、タイムアウト値を 120 秒に設定する場合は、次のように設定します。
conf_http_HTTPTransport.io.timeout.millis=120000
- このファイルが apigee によって所有されていることを確認します。
chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
- Message Processor を再起動します。
/opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
- 複数の Message Processor がある場合は、すべての Message Processor で上記の手順を繰り返します。
提案: 次の順序で、各種コンポーネントのタイムアウト値を設定します。クライアントのタイムアウト > Router のタイムアウト > Message Processor のタイムアウト > API プロキシ内のタイムアウト |
Edge による API リクエストの処理が遅い
Edge が非常に遅い、または API リクエストを処理するのに時間がかかる場合は、504 Gateway Timeout エラーが発生します。
診断
- Edge UI で影響を受ける API をトレースします。
- エラーが発生するのを待つか、API 呼び出しがある場合は、API 呼び出しを行い、504 Gateway Timeout エラーを再現します。
- この場合、トレースで成功したレスポンスが表示されることがあります。
- Router / クライアント(タイムアウト期間が短い方)の指定されたタイムアウト期間内に Message Processor が応答しないため、Router / クライアントがタイムアウトします。ただし、Message Processor は引き続きリクエストを処理し、正常に完了する場合があります。
- さらに、Message Processor で設定された HTTPTransport.io.timeout.millis の値は、Message Processor が HTTP / HTTPS バックエンド サーバーと通信する場合にのみトリガーされます。つまり、API プロキシ内のポリシー(Service Callout ポリシー以外)に時間がかかる場合、このタイムアウトはトリガーされません。
- エラーが発生したら、経過時間が最も長い特定のリクエストを調べます。
- 各フェーズの経過時間を確認し、ほとんどの時間が費やされているフェーズをメモします。
- Service Callout ポリシー以外のポリシーで最も長い経過時間を特定した場合は、Edge がリクエストを処理するのに時間がかかることを示します。
- 次に、JavaScript ポリシーの経過時間が非常に長い UI トレースの例を示します。
- 上記の例では、JavaScript ポリシーで約 245 秒という非常に長い時間がかかることがわかります。
解決策
- 応答に時間がかかったポリシーと、処理に時間がかかる可能性があるカスタムコードがあるかどうかを確認します。そのようなコードがある場合は、識別されたコードを修正 / 最適化できるかどうかを確認します。
- 処理時間が長くなる可能性があるカスタムコードがない場合は、Message Processor で CPU またはメモリの使用率が高いかどうかを確認します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
<JAVA_HOME>/bin/jstack -l <pid> > <filename>
- Message Processor のメモリ使用率が高い場合は、次のコマンドを使用してヒープダンプを生成します。
sudo -u apigee <JAVA_HOME>/bin/jmap -dump:live,format=b,file=<filename> <pid>
- 次のコマンドを使用して Message Processor を再起動します。これにより、CPU とメモリの使用率が下がります。
/opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
- API 呼び出しをモニタリングし、まだ問題が存在するかどうかを確認します。
- CPU / メモリの使用率が高い原因を調査できるように、Apigee サポートにスレッドダンプ、ヒープダンプ、Message Processor のログ(
/opt/apigee/var/log/edge-message-processor/logs/system.log)
を提供します。
- Message Processor の CPU 使用率が高い場合、次のコマンドを 30 秒ごとに実行し、3 つのスレッドダンプを生成します。
API Monitoring を使用して問題を診断する
注: このセクションの手順を実施できるのは Public Cloud ユーザーだけです。
API Monitoring では、問題領域を簡単に切り分けて、エラー、パフォーマンス、レイテンシの問題とその原因(デベロッパー アプリ、API プロキシ、バックエンド ターゲット、API Platform など)を診断できます。
API Monitoring を使用して API での 5xx 問題をトラブルシューティングする方法を説明するサンプル シナリオに従ってください。たとえば、504 ステータス コードの数が特定のしきい値を超えたときに通知を行うようにアラートを設定します。