Google Cloud API Gatewayのタイムアウト値をカスタマイズする

2024/04/17に公開

3行まとめ

  • Google CloudのAPI Gatewayのデフォルトのタイムアウト値は15秒らしい(ドキュメントは見つからず)
  • API GatewayはGoogleが開発したOpenAPI仕様の拡張機能を備えたESP(Extensible Service Proxy)v2をサポートしている
  • OpenAPIの拡張機能のdeadlineプロパティを用いてタイムアウト値をカスタマイズできる

API GatewayでHTTPステータス504が度々発生していた

以下のようなアーキテクチャを構築し、Slackからメンションを飛ばしてGoogle CloudのCloud Functionsでリクエストを処理、レスポンスをSlackのスレッドで受け取る仕組みを検証していた。(このアーキテクチャの詳細については後日別エントリにまとめる予定)
apigateway-config-timeout-01

セキュリティなどの観点からAPI Gatewayを前段に噛ませる必要が生じ、上記のアーキテクチャを構築して動作確認を実施していたところ、正常にリクエストとレスポンスのやり取りが完了している中で以下のようなログを発見した。
apigateway-config-timeout-02

大体15秒後にHTTPステータスの504が発生している。ちなみにこのステータスコードはresponse_code_detail: "response_timeout"であり、API Gatewayにてタイムアウトが発生していることが分かった。
Googleで検索をかけてみるとAPI Gatewayのタイムアウト値のデフォルトは15秒らしいという情報が得られた。

https://www.googlecloudcommunity.com/gc/Integration-Services/API-Gateway-Default-Timeout/m-p/550607#M255

また、同様のタイムアウトが発生し回避策を取ったブログも発見した。
https://www.exceedsystem.net/2023/06/14/how-to-solve-http-504-error-on-api-gateway-of-google-cloud-platform/
https://sobacha22.hatenablog.com/entry/2024/01/01/161316

現在実装している処理は完了までに最長で3分近くかかってしまうこともあるため、動作上問題はないが504エラーの頻発を回避する実装が必要となっていた。そこで、API GatewayのAPI構成にてタイムアウト値を指定してみることにした。

API GatewayのAPI構成にタイムアウト値を設定する

Google CloudのAPI GatewayはOpenAPI SpecificationのVersion2.0をサポートしている。
このOpenAPI SpecificationはGoogleが独自に開発した拡張機能を含めた以下構成もサポートしている。

  • API の名前と、短い説明付きの optional-string が表示される title。
  • API キーを使用するためのパスの構成方法
  • 認証用のさまざまなセキュリティ スキーム
  • OpenAPI の拡張

https://cloud.google.com/api-gateway/docs/openapi-overview?hl=ja

Googleが開発した拡張機能は、x-google-という接頭辞がついており、x-google-backendの拡張機能の中には以下のような設定があった。

deadline: double
省略可。リクエストに対する完全な応答を待機する秒数。構成された期限よりも時間がかかる応答はタイムアウトします。デフォルトの期限は 15.0 秒です。
正でない値は受け入れられません。その場合、ESPv2 では自動的にデフォルト値が使用されます。
期限を無効にすることはできませんが、たとえば 1 時間を表す 3600.0 などの高い数値に設定することは可能です。

https://cloud.google.com/endpoints/docs/openapi/openapi-extensions?hl=ja#deadline

ログから確認できる現状の挙動がまさにこのデフォルトの期限に該当していることが分かる。また、以下の注意書きもあった。

注: deadline プロパティは ESPv2 の新機能です。この機能は ESP ではサポートされていません。

API Gatewayのログを確認すると以下のような記載があり、ESPv2を使っていることが確認できた。

{
︙
response_code_detail: "response_timeout"
service_agent: "ESPv2/2.46.0"
service_config_id: "hogehoge"
timestamp: XXXXXXXX.XXXXX
}

なので、deadlineプロパティを実装してタイムアウト値をデフォルトの15秒から延長してみることにした。

実装したAPI構成

paths:
  /hoge:
    post:
      summary: Post request from Slack
      operationId: hoge
      x-google-backend:
        address: <Cloud FunctionsのHTTPエンドポイント>
        deadline: 180.0

pathsのプロパティを上記のように記載し、3分(180秒)の応答待機時間を設定した。これで15秒以上かかる処理に対してHTTPステータス504が返ってくることはなくなるはずだ。

検証結果

Cloud FunctionsにSlackへのレスポンスをsleepで60秒待機させる実装をして、動作確認を行った。
API Gatewayのログは以下のようになり504のステータスが発生しなくなったことが確認できた。

apigateway-config-timeout-03

まとめ

Google Cloud API Gatewayのデフォルトのタイムアウト値を変更したくなったらdeadlineプロパティを使えば大丈夫だということが確認できた。
OpenAPI拡張に関するドキュメントがAPI GatewayではなくCloud Endpointsのドキュメント内にあったりと実際に挙動を確認するまでは心配なところがあったので動作確認ができてホッとした。
実際にログをちゃんと読んでみるとESPv2を利用していることなども確認できたので、ログを読むことの大切さを改めて痛感した。
あとこれは個人的にSwaggerの練度が低いせいであったのだが、Googleの拡張機能についてはSwagger Editorでデバッグができず(Googleが拡張したものなので当たり前なのだが)API GatewayにAPI構成を登録する時に何度かエラーが発生して修正が大変だった。APIクンフーを鍛える良いきっかけになりそうだ。

Discussion