はじめに
Open JDK 11から導入されたHTTP ClientでHTTP Keep Alive Timeoutを設定するサンプルです。
サーバー側からのコネクションクローズとクライアントからのリクエストが同時処理されたタイミングでの通信エラーを防止するため、クライアント側のKeep Alive Timeout値をサーバー側より短くするのは鉄則です。
そのため、クライアント側の設定方法を押さえておくことは、重要です。
利用するJDK Version
執筆時点で最新のOpen JDK 13を利用します。
また、コードの実行にはjshellを利用します。
余談ですが、jshellはまじで便利ですね。
~ $ java --version
openjdk 13.0.1 2019-10-15
OpenJDK Runtime Environment (build 13.0.1+9)
OpenJDK 64-Bit Server VM (build 13.0.1+9, mixed mode, sharing)
設定方法
HTTP ClientのKeep Alive Timeoutは、javaプロパティの jdk.httpclient.keepalive.timeout
で設定可能です。
-Djdk.httpclient.keepalive.timeout=60
または
System.setProperty("jdk.httpclient.keepalive.timeout", "99999");
などの方法で設定可能です。
この設定値は、jdk.internal.net.http.ConnectionPool
クラスで読み込まれます。
タイムアウト値を保持する変数は、staticなので、上記クラスのロード前に設定する必要があり、ロード後は変更不可なようです(未検証)。
なお、ソースコード見る限り、Open JDK13ではデフォルト値は1200秒です。
ConnectionPoolのソース(JDK 13)は、ここから参照できます。
サンプル
jshellでのサンプルです。
qiita.comへHTTP GETします。
Keep Alive Timeoutは、10秒に設定します。
jshell> import java.net.http.*
jshell> System.setProperty("jdk.httpclient.keepalive.timeout", "10")
$1 ==> null
jshell> HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build()
client ==> jdk.internal.net.http.HttpClientImpl@57baeedf(1)
jshell> HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://qiita.com")).build()
request ==> https://qiita.com GET
jshell> HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString())
response ==> (GET https://qiita.com) 200
設定の有効性確認
上記のサンプルだけでは、Timeout値の変更有無を確認できないので、OSのnetstatコマンドでTCPの状態を監視してみます。
下例では、netstatコマンドを1秒ごとに実行し、コマンド結果をqiita.comのPublic IPアドレスで絞り込んでいます。
while true; do date; netstat -n -p TCP | egrep "13.114.xxx.xxx|176.34.xxx.xxx|13.113.xxx.xxx"; sleep 1; done
2019年 11月21日 木曜日 18時31分34秒 JST
2019年 11月21日 木曜日 18時31分35秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分36秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分37秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分38秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分39秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分40秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分41秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分42秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分43秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分44秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分45秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 ESTABLISHED
2019年 11月21日 木曜日 18時31分46秒 JST
tcp4 0 0 xxx.xxx.xxx.xxx.62156 13.114.xxx.xxx.443 TIME_WAIT
TCPコネクションが確立後、10秒間ESTABLISHED
となり、1秒後にアクティブクローズしたため、TIME_WAIT
へ移行していることが分かります。
設定は有効であることが確認できました。