yassy's note

なんかかきます

DNS名前解決時のタイムアウト

qiita.com

この記事を読んで、これマ?と思ったので実際にやってみた。
環境はCentOS7。

事前準備

こんな感じで適当な名前解決先を指定しておく。
どれも無効なIPなので失敗します。

/etc/resolv.conf

; generated by /usr/sbin/dhclient-script
search ap-northeast-1.compute.internal
nameserver 8.8.8.9
nameserver 8.8.8.10
nameserver 8.8.8.11

やってみた

まずは、デフォルト設定である、timeout:5、attempts:2から。
必要なところだけ抜き出している。

[root@ip-172-31-43-45 ~]# strace route

poll([{fd=4, events=POLLIN}], 1, 5000)  = 0 (Timeout)
poll([{fd=5, events=POLLIN}], 1, 3000)  = 0 (Timeout)
poll([{fd=6, events=POLLIN}], 1, 6000)  = 0 (Timeout)

poll([{fd=4, events=POLLIN}], 1, 5000)  = 0 (Timeout)
poll([{fd=5, events=POLLIN}], 1, 3000)  = 0 (Timeout)
poll([{fd=6, events=POLLIN}], 1, 6000)  = 0 (Timeout)

待ち時間はpollの第4引数が示している。単位はミリ秒。
今回はnameserverを3台設定しているので、1台めは5秒、2台めは3秒、3台めは6秒待機している。
attemptsは2を指定しているので、これを2セット行っている。

この辺は最初に挙げた記事の内容と合致している。

1回目の問い合わせ時は、options timeout:nの秒数をセットして問い合わせる。
2回目の問い合わせ時は、1回目のタイムアウト秒を2倍した値を、登録してあるnameserverの数で割った値で問い合わせる。
3回目以降の問い合わせ時は、2回目の問い合わせ時の2倍の値を使う。

これを1セットとし、options attempts:nの回数分繰り返す。

以上のことから、名前解決のエラーが返ってくるまで14×2=28秒かかると計算できる。
こちらについても、timeコマンドを使用して測定してみる。

[root@ip-172-31-43-45 ~]# time route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    0      0        0 eth0
172.31.32.0     0.0.0.0         255.255.240.0   U     0      0        0 eth0

real    0m28.036s
user    0m0.000s
sys     0m0.008s

確かに、机上計算と一致している。

他のパラメータでやってみる

次に、attempts:3、timeout:7で試してみる。

机上計算では、
1回目:7000ミリ
2回目:7000×2÷3=4666.666...
3回目:4666.666...×2=9333.333...
となり、合計タイムアウト値は20999×3=62997ミリ秒=62.997秒と考えられる。

こちらも実際に確認してみる。

[root@ip-172-31-43-45 ~]# strace route

poll([{fd=4, events=POLLIN}], 1, 7000)  = 0 (Timeout)
poll([{fd=5, events=POLLIN}], 1, 4000)  = 0 (Timeout)
poll([{fd=6, events=POLLIN}], 1, 9000)  = 0 (Timeout)

poll([{fd=4, events=POLLIN}], 1, 7000)  = 0 (Timeout)
poll([{fd=5, events=POLLIN}], 1, 4000)  = 0 (Timeout)
poll([{fd=6, events=POLLIN}], 1, 9000)  = 0 (Timeout)

poll([{fd=4, events=POLLIN}], 1, 7000)  = 0 (Timeout)
poll([{fd=5, events=POLLIN}], 1, 4000)  = 0 (Timeout)
poll([{fd=6, events=POLLIN}], 1, 9000)  = 0 (Timeout)
[root@ip-172-31-43-45 ~]# time route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    0      0        0 eth0
172.31.32.0     0.0.0.0         255.255.240.0   U     0      0        0 eth0

real    1m0.056s
user    0m0.002s
sys     0m0.002s

ほう。
straceの結果を見ると、端数は百の位で切り捨てされるということが分かる。
そのため、実際の待ち時間は(7000+4000+9000)×3=20000×3=60000ミリ秒=60秒
となり、timeコマンドの結果と一致する。

うーん、勉強になった。