Closed9

GoogleApisライブラリのExponential Backoffを追いたい

anizozinaanizozina

背景

  • GoogleApisを利用した実装で、ライブラリがどこまで考慮して実装されているのかを追いたかった
  • 例えば、公式ドキュメントによればaccess tokenが期限切れの場合にはrefresh tokenを使用して再取得してくれる、とある
  • 同じような仕組みで、リソースへのアクセスが一時的に制限されていた場合の再実行の仕組みが実装されているのか、どのように実装されているのかが気になった

ゴール

  • GoogleApisにおいて、再実行の処理がどこでどのように実装されているのか明らかになっていること
anizozinaanizozina

進めかた

ライブラリのコードを追うのに慣れていないので愚直に上から下まで読んでいく

バージョン等

anizozinaanizozina

gaxios上の実装を追う

おそらくエンドポイントとして利用されるのは request メソッドだと思われる。
ref. https://github.com/googleapis/gaxios/blob/v6.4.0/src/gaxios.ts#L133

_request で実際にリクエストを投げているのは上から渡ってきているoptsで指定されたadapterにあると思われる。
ただ、ここを追わんでもこのロジックのtry-catchでそれっぽいことをやっているように見える。
ref. https://github.com/googleapis/gaxios/blob/v6.4.0/src/gaxios.ts#L183-L201
以下内容を抽出

const err =
        e instanceof GaxiosError
          ? e
          : new GaxiosError((e as Error).message, opts, undefined, e as Error);

      const {shouldRetry, config} = await getRetryConfig(err);
      if (shouldRetry && config) {
        err.config.retryConfig!.currentRetryAttempt =
          config.retryConfig!.currentRetryAttempt;

        // The error's config could be redacted - therefore we only want to
        // copy the retry state over to the existing config
        opts.retryConfig = err.config?.retryConfig;

        return this._request<T>(opts);
      }

shouldRetryだったらもっかい同じメソッドを叩いてくれていそう。
ただ、これだけみるとexponential backoffの実装に見えない。
retryConfigがPromiseを返してくるのが怪しいので覗いてみる。

anizozinaanizozina

getRetryConfig

出発点はここ
ref. https://github.com/googleapis/gaxios/blob/v6.4.0/src/retry.ts#L16

雑多なメモ的な残し

ここらへん以降にexponential backoff的な実装がある
あとはコメントに書いてある通りではあるが、retryのbackoffを計算してその分setTimeoutで待っている。

anizozinaanizozina

exponential backoffの実装だけ抜き出す

多分こんな感じで計算自体はされてるはず

const retryDelay = (attempt: number = 0): number => {
  return (attempt ?? 100) + ((Math.pow(2, attempt) - 1) / 2) * 1000
}

1回目は即時実行、2回目以降は指数的にリトライにかかる時間が増加する。
ref. https://www.typescriptlang.org/play?#code/FAYw9gdgzgLgBAJwKYwQTwCJIDYEM1wC8cAFLjDEgLYAOMAXHBAK5UBGSCRcADAJSMW7TkQB8cAN7A4MxCmYIIpcpVrwA-OrgBGHvzgBqUiQCy5ABYA6GmADuJAEwAaOCup0+cALQ7PAejgHTwAqHT0eYABfYGBsFDgAS24eAG5QSFg4ADMEhFgsPAJiZFRMHHwSBIMDPnToeCgkcAgAEwL8bhL0drRK6trmzJhzXLbyorlSnr6ausyssARhns6UbvGZgYz4HKzl8dWpjarZubA4y2wwAHMSKVls3Pzxp2lZRuaxwteH4dGen6yBZLcwAt4yXb7QpRPhAA

anizozinaanizozina

ゆらぎが必要な理由

AWSのドキュメントだけど、ここで言及されているジッターを入れてるだけか。

過負荷または競合が障害の原因である場合、バックオフが非常に役に立たないことがよくあります。これは相関関係が原因です。失敗したすべてのコールが同じ時間にバックオフされた場合、再試行時に再び競合または過負荷が発生します。私たちのソリューションはジッターです。ジッターはバックオフにある程度のランダム性を追加して、再試行を時間内に分散させます。

ref. https://aws.amazon.com/jp/builders-library/timeouts-retries-and-backoff-with-jitter/

このスクラップは2024/04/14にクローズされました