Java HTTP ClientでHTTP Keep Alive Timeoutを設定する

# はじめに
Open JDK 11から導入されたHTTP ClientでHTTP Keep Alive Timeoutを設定するサンプルです。

サーバー側からのコネクションクローズとクライアントからのリクエストが同時処理されたタイミングでの通信エラーを防止するため、クライアント側のKeep Alive Timeout値をサーバー側より短くするのは鉄則です。

そのため、クライアント側の設定方法を押さえておくことは、重要です。

# 利用するJDK Version
執筆時点で最新のOpen JDK 13を利用します。
また、コードの実行にはjshellを利用します。
余談ですが、jshellはまじで便利ですね。

```shell-session
~ $ 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)は、[ここ](https://github.com/openjdk/jdk13/blob/master/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java)から参照できます。

# サンプル
jshellでのサンプルです。
qiita.comへHTTP GETします。
Keep Alive Timeoutは、10秒に設定します。

```shell-session:jshell実行サンプル
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アドレスで絞り込んでいます。

```shell-session:netstat
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`となり、１秒後にアクティブクローズしたため、`TIME_WAIT`へ移行していることが分かります。

設定は有効であることが確認できました。