Boto3のコネクションタイムアウト値について教えてください

2021.12.08

この記事はアノテーション株式会社 AWS Technical Support Advent Calendar 2021のカレンダー | Advent Calendar 2021 - Qiita 8日目の記事です。

困っていた内容

AWS SDK for Python (Boto3)におけるリトライ処理の動作を確認するため、EC2上のPythonスクリプトで、Boto3のタイムアウトの処理をテストしました。

  • connect_timeoutのtimeout値を5秒
  • max_attemptsを3回
  • retrymodeをstandard

上記の設定をして SecretsManager にアクセスしました。

この設定だと、20秒ほどでタイムアウトする想定になりますが、 実際に試してみると、65秒経過後にタイムアウトが発生しました。 想定とのギャップが発生する理由を教えてください。

(セキュリティグループのアクセス許可を外した状態でテストを実施しました)

import boto3
from botocore.config import Config

config = Config(
    connect_timeout=5,
    retries={
        'max_attempts': 3,
        'mode': 'standard'
    })

client = boto3.client(
    service_name='secretsmanager',
    region_name='ap-northeast-1',
    config=config
)

どう対応すればいいの?

東京リージョンで、SecretsManagerのエンドポイントのIPアドレスを確認すると、3件登録されていました。

dig secretsmanager.ap-northeast-1.amazonaws.com
...
secretsmanager.ap-northeast-1.amazonaws.com. 41    IN A 54.249.xx.xx
secretsmanager.ap-northeast-1.amazonaws.com. 41    IN A 54.168.xx.xx
secretsmanager.ap-northeast-1.amazonaws.com. 41    IN A 54.238.xx.xx

※ なお、DNSに登録されているエンドポイントのIPアドレスの数は、サービスにより異なるようです。

この状態で上記のテストを行った場合、1 attempt毎に3回の接続試行をしているので、
5 ✕ 3 = 15
15秒ほどかかります。

一方で、DNSを参照しない形で、 /etc/hosts でSecretsManagerのエンドポイントのIPアドレスを、1件だけ指定した場合は、 1 attempt毎に1回の接続試行をします。

パラメータとして
connect_timeout:5
max_attempts:3
を指定した場合、それぞれ下記のような動作になります。

DNSから3件のIPアドレスが返される場合:

attempt1 17:00:00
 (5×3=15秒)
attempt2 17:00:15
 (5×3=15秒)
attempt3 17:00:30
 (5×3=15秒)
attempt4 17:00:45
 (5×3=15秒)
→ 約60秒後にエラーで終了

hostsファイルで1件だけIPアドレスを指定した場合:

attempt1 17:00:00
 (5×1=5秒)
attempt2 17:00:05
 (5×1=5秒)
attempt3 17:00:10
 (5×1=5秒)
attempt4 17:00:15
 (5×1=5秒)
→ 約20秒後にエラーで終了

※ 実際には、エクスポネンシャルバックオフ・アルゴリズムによるジッター(ランダムな遅延時間)が数秒ほど加算されます。

参考資料

[1] Config Reference — botocore 1.23.21 documentation

[2] AWS SDK for Python (Boto3)の エラーの再試行について

[3] Boto3 に追加されたリトライ処理モードを利用する

[4] AWSでのエラー再試行とエクスポネンシャルバックオフ - AWS 全般のリファレンス