次のコードを使用して、サーバーにリクエストを送信しようとしています。常に3回目のリクエストで失敗しました。
import Java.io.InputStreamReader;
import Java.io.UnsupportedEncodingException;
import Java.nio.charset.Charset;
import org.Apache.http.HttpEntity;
import org.Apache.http.HttpResponse;
import org.Apache.http.HttpStatus;
import org.Apache.http.HttpVersion;
import org.Apache.http.client.HttpClient;
import org.Apache.http.client.methods.HttpPost;
import org.Apache.http.entity.ContentType;
import org.Apache.http.entity.StringEntity;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.Apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.Apache.http.params.BasicHttpParams;
import org.Apache.http.params.CoreConnectionPNames;
import org.Apache.http.params.HttpParams;
import org.Apache.http.params.HttpProtocolParams;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
public class HttpClientTest {
private HttpClient client;
public HttpClientTest() {
HttpParams params = new BasicHttpParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15000);
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 15000);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "utf-8");
HttpProtocolParams.setUseExpectContinue(params, true);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
cm.setMaxTotal(100);
client = new DefaultHttpClient(cm, params);
while (true) {
HttpPost mPost = new HttpPost("http://myip/myservice");
JSONObject json = new JSONObject();
try {
json.put("serialNumber", "abcd");
} catch (JSONException e1) {
e1.printStackTrace();
}
StringEntity s = null;
try {
s = new StringEntity(json.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
s.setContentEncoding("UTF-8");
s.setContentType("application/json");
mPost.setEntity(s);
JSONObject response = null;
System.out.println("HttpClientTest ---> send post");
HttpResponse mHttpResponse;
try {
mHttpResponse = client.execute(mPost);
System.out.println("HttpClientTest ---> get response");
if(mHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
HttpEntity entity = mHttpResponse.getEntity();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
response = new JSONObject(new JSONTokener(new InputStreamReader(entity.getContent(), charset)));
System.out.println("HttpClientTest ---> get result:" + response.toString());
} else {
mPost.abort();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
HttpClientTest t = new HttpClientTest();
}
}
次のような例外:
org.Apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
at org.Apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.Java:417)
at org.Apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.Java:300)
at org.Apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.Java:224)
at org.Apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.Java:401)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:820)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:754)
at org.Apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.Java:732)
at com.i360r.client.takeaway.network.HttpClientTest.<init>(HttpClientTest.Java:68)
at com.i360r.client.takeaway.network.HttpClientTest.main(HttpClientTest.Java:88)
私は同じ問題を抱えていて、修正を見つけました。このタイムアウトは、接続リークが原因です。私の場合、httpDelete
メソッドを使用し、応答を消費していません。代わりに、応答のステータスを確認します。
修正は、応答エンティティを消費する必要があるということです。システムリソースを適切に解放するには、エンティティに関連付けられているコンテンツストリームを閉じる必要があります。
したがって、エンティティコンテンツが完全に消費され、コンテンツストリームが存在する場合はそれが閉じられるようにするEntityUtils.consumeQuietly(response.getEntity());
を使用しました。
修正しました! finally
ブロックにmPost.releaseConnection()
を追加します。
try {
} catch (Exception e) {
} finally {
mPost.releaseConnection();
}
パッケージを更新するorg.Apache.httpcomponents
から4.2.1
応答を取得する行をtry-with-resources内に配置し、HttpResponseの代わりにCloseableHttpResponseを次のように使用します。
try(final CloseableHttpResponse mHttpResponse = client.execute(mPost);)
{
System.out.println("HttpClientTest ---> get response");
....remainder code
MHttpResponseオブジェクトは自動的に消費され、自動的に閉じられます
お役に立てれば!
これは、DropWizard 0.6.2でApacheHttpClient
を使用している場合にも発生する可能性があります。これは、舞台裏でMultiThreadedHttpConnectionManager
をデフォルト構成で作成します。 詳細はこちら 。
したがって、この構成では、サーバーが常に圧迫され、常に同じホストにリクエストを送信している場合、一度に最大2つの接続を実行できます。
実際に...応答が完了したら、接続を閉じる必要はなく、閉じてください。
CloseableHttpResponse response = client.execute(httpPost, context);
...必要なことをしてください...
response.close();
Rama が言ったように、これは接続リークの兆候である可能性があります。
releaseConnection()
はこの問題の解決に役立つ可能性がありますが、根本的な原因を見つける必要があるかもしれません。
また、これは、timeout
のHttpClient
configがない場合に発生するリース可能な利用可能な接続がないために発生する可能性があります。この場合、releaseConnection()
は役に立ちません。