クライアントマシンからREST
サーバーに、Jersey
を使用して通信するために使用される(大幅に簡略化された)コードは次のとおりです。開始時に接続を確立するための5分のタイムアウトと、下位のソケットからの読み取りのための2分のタイムアウトがあります。クライアントで読み取りタイムアウト後にジャージーサーバーCLOSE_WAITがリークします
public class JerseyClient {
private final Map<Action, WebResource> resources;
public JerseyClient(URI uri) {
this.resources = new EnumMap<Action, WebResource>(Action.class);
this.resources.put(Action.Put, getClient().resource(Action.Put.getURI()));
this.resources.put(Action.Query, getClient().resource(Action.Query.getURI()));
}
private String submit(Action action, String input) throws Exception {
WebResource resource = this.resources.get(action);
ClientResponse response = null;
synchronized (resource) {
try {
response = resource.accept(MediaType.APPLICATION_JSON_TYPE,
MediaType.TEXT_PLAIN_TYPE).type(MediaType.APPLICATION_JSON_TYPE).
post(ClientResponse.class, input);
String responseString = null;
// Handle the response and produce a response string...
return responseString;
} finally {
if (response != null) {
response.close();
}
}
}
}
private static Client getClient() {
Client client = Client.create();
client.setReadTimeout(2*60*1000);
client.setConnectTimeout(5*60*1000);
return client;
}
private enum Action {
Put, Query;
public URI getURI(){
switch (this) {
case Put:
return URI.create("PUT_URI");
case Query:
return URI.create("QUERY_URI");
default:
throw new InvalidStateException("Illegal action");
}
}
}
}
クライアントで読み取りタイムアウトが発生しない限り、上記のコードは期待通りに機能します。この場合、SocketTimeoutException
がスローされ、上記のJerseyClient
メソッドのsubmit()
メソッドの応答オブジェクトはnull
のままであるため、基底ソケットは決して完全に閉じられません。 、他方の側に、サーバはCLOSE_WAIT
状態に入るため
は明らかに(すなわち、それはTCP
仕様に従って、クライアントからFIN
パケットを受信した)クライアントによるソケットの部分的閉塞があります。しかし、ACK
はクライアント(response.close()
が呼び出された場合に送信される)から決して得られないので、(図のようにnetstat
)の接続を維持するので、クライアントからのREST
コールのタイムアウトが発生するたびにCLOSE_WAIT
サーバー上で
上記のコードを完全に再エンジニアリングすることなく、問題を解決する方法はありますか?
もちろん、CLOSE_WAITについては当然です。問題はハリーで書かれましたが、修正されました。シナリオは当初記載されたままである。ありがとうございました。 :-) – PNS
シナリオは、サーバーがソケットをクローズしておらず、クライアントが持っていることです。これはもともと説明したものとまったく逆です。 – EJP
私たちは、多くのCLOSE_WAIT接続が存在するという事実に基づいて、この問題を追跡しています。ドキュメンテーションに基づいて誰が何をしたかにかかわらず、 'response.close()'がクライアントで呼び出される必要があります。上記のコードでこれを行う方法はありますか?それが主な質問です。ありがとう。 – PNS