BigQueryリモート関数でのエラー発生時の再試行をどう処理するか
導入
BigQueryとCloud Functions、Cloud Runを結合することで、PythonやGoなどのコードをSQLから実行できるリモート関数という機能があります。このリモート関数には以下の仕様があります。
成功したレスポンスの場合、エンドポイントから HTTP レスポンス コード 200 が返されます。それ以外の値を受け取ると、BigQuery はレスポンスを失敗とみなし、HTTP レスポンス コードが 408、429、500、503、504 の場合は、なんらかの内部上限に達するまで再試行します。
リモート関数を使用する際には、この仕様について事前に理解しておくことが重要です。おそらく2024年8月3日現在、BigQuery側でこのリトライを抑制する設定項目は無く、関数側(Cloud Functions、Cloud Run)で適切な処理を実装する必要があります。呼び出す関数側の実装が不十分な場合、この仕様が厄介な問題を引き起こす可能性があります[1]。以下では、この仕様を踏まえた設計・実装時に考慮すべき観点を示します。
関数側の設計・実装時に考える観点
1. リトライによって復旧する見込みのあるエラーを洗い出す
例えば、一時的なネットワークエラーやDBコネクションエラーなど、リトライにより復旧する可能性がある場合では、関数コードで500エラーを発生させるような実装も考えられるかと思います。
また、関数のスペックとしてリソース負荷を抑えるためにコンカレンシを小さめに設定している場合、429エラーを発生させてリトライさせることで、環境に悪影響を与えることなく関数を正常終了させることも可能です。
以上は一例ですが、リトライによって復旧する見込みのあるエラーを明確に把握し、その場合においてはリトライが発生するエラーコードを返す実装にすることが選択肢となり得ます。
ただしこの場合にも何かしらの監視を行い、意図せず多発するリトライが発生した場合に気づき対処する手段を設けておくべきでしょう。
2. その他はリトライが発生しないようにエラー処理する
一方で、予期しないエラーについては、全て400エラーなどで処理し[2]、リトライを発生させない方が安全に倒れる場合が多いように思われます。この場合、リトライを実行することなくクエリがエラーとなり、無駄なリソースを消費するなどの問題を防ぐことができるかと思います。
コンソールからクエリを実行した際にエラーが出た場合、次のようなメッセージが出て直ちにクエリが停止します。
一方で、500エラーなどを返す状態では、内部上限に達するか手動でクエリをキャンセルするまで停止しません。
まとめ
以上のように、リモート関数を設計・実装する際には、リトライに関する仕様を理解し、適切なエラー処理を行うことが重要です。リトライが有効に働く場合にはリトライが発生するエラーコードを返す実装にすることが考えられますが、その他はリトライが発生しないような実装にするのが無難かと思います。
世界のラストワンマイルを最適化する、OPTIMINDのテックブログです。「どの車両が、どの訪問先を、どの順に、どういうルートで回ると最適か」というラストワンマイルの配車最適化サービス、Loogiaを展開しています。recruit.optimind.tech/
Discussion