私たちは、JDK11使用しているjava.net.http
APIからデータを取得するためにHTTPクライアントを。私たちは応答を受信した後、接続がTCPの状態で当社のサーバーにオープンしたままにCLOSE_WAIT
クライアントが接続を閉じなければならないことを意味し、。
以下からのRFC 793用語:
CLOSE-WAIT - ローカルユーザからの接続終了要求を待って表します。
これは、ステートレスのREST APIとしてJavaの12で実行されているWildFly 16上で動作し、当社のクライアントコードです。なぜこれが起こっている私たちは理解していません。
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class SocketSandbox {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder().version(Version.HTTP_1_1).build();
try (var listener = new ServerSocket(59090)) {
System.out.println("Server is running...");
while (true) {
try (var socket = listener.accept()) {
HttpRequest request = HttpRequest
.newBuilder(URI.create("<remote_URL>"))
.header("content-type", "application/json").build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
var out = new PrintWriter(socket.getOutputStream(), true);
out.println(String.format("Response HTTP status: %s", response.statusCode()));
}
}
}
}
}
私たちは、HTTP応答が処理された意味する「ステータスコード」を取得します。
他のエンドポイントを呼び出すために、同じコードを使用する場合の接続は大丈夫です。我々が求めているリモートAPIと特定の問題のようですが、Java HTTPクライアントが開かれた接続を維持している理由はまだ我々は理解していません。
我々は両方のWindowsとLinuxマシンを試みたが、WildfFlyのさえスタンドアロンの外側が、同じ結果が発生します。各要求、でも私たちのステートレスクライアントからそれをやって、レスポンスを受信した後、それぞれがとして残されCLOSE_WAIT
、決して近いです。
我々シャットダウンJavaプロセス場合、接続が表示されなくなります。
HTTPクライアントによって送信されたヘッダ:
connection: 'Upgrade, HTTP2-Settings','content-length': '0',
host: 'localhost:3000', 'http2-settings': 'AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA',
upgrade: 'h2c',
user-agent': 'Java-http-client/12'
サーバーのリターンはヘッダとレスポンス: Connection: close
アップデート(1)
我々は微調整に実装クラスでプールパラメータを試してみましたjdk.internal.net.http.ConnectionPool
。
これは、問題を解決しませんでした。
System.setProperty("jdk.httpclient.keepalive.timeout", "5"); // seconds
System.setProperty("jdk.httpclient.connectionPoolSize", "1");
アップデート(2)
Apache HTTP接続Lは約90秒間CLOSE_WAIT状態のままになったが、それはその時間の後に接続することが可能です。
メソッドが呼び出すHttpGet.releaseConnection()
近い、すぐに接続を強制。
HttpClient client = HttpClients.createDefault();
HttpGet get = new HttpGet("https://<placeholderdomain>/api/incidents/list");
get.addHeader("content-type", "application/json");
HttpResponse response = client.execute(get);
// This right here did the trick
get.releaseConnection();
return response.getStatusLine().getStatusCode();
そして、でOkHttpの箱から出して期待通りに働いていたクライアント、何の接続が立ち往生していません。
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://<placeholderdomain>/grb/sb/incidentes/listar")
.header("content-type", "application/json").build();
Response response = client.newCall(request).execute();
return response.body().string();
我々はまだ我々は、コードを書き直す必要がないように、それは、Java-HTTPクライアントで働くようにする方法を見つけようとしています。
実装のバグとして提出し、確認しました。