HttpClient
の実行全体のタイムアウトを指定する方法はありますか?
私は次を試しました:
httpClient.getParams().setParameter("http.socket.timeout", timeout * 1000);
httpClient.getParams().setParameter("http.connection.timeout", timeout * 1000);
httpClient.getParams().setParameter("http.connection-manager.timeout", new Long(timeout * 1000));
httpClient.getParams().setParameter("http.protocol.head-body-timeout", timeout * 1000);
リモートホストが1バイト/秒であってもデータを送り返す場合を除いて、実際に正常に動作します。しかし、ホストが応答するかどうかに関係なく、最大10秒で接続を中断します。
現在、その種の最大リクエスト期間を設定する方法はありません:基本的にあなたは言いたい私は気にしません特定のリクエストステージはタイムアウトになりますが、リクエスト全体が15秒より長く続くことはできません(たとえば)。
あなたの最善の策は、別のタイマーを実行し、それが期限切れになったら、HttpClientインスタンスが使用する接続マネージャーを取得し、接続をシャットダウンして、リンクを終了することです。それがあなたのために働くかどうか私に知らせてください。
Httpclientの新しいバージョン(例:http components 4.3- https://hc.Apache.org/httpcomponents-client-4.3.x/index.html ):
int CONNECTION_TIMEOUT_MS = timeoutSeconds * 1000; // Timeout in millis.
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(CONNECTION_TIMEOUT_MS)
.setConnectTimeout(CONNECTION_TIMEOUT_MS)
.setSocketTimeout(CONNECTION_TIMEOUT_MS)
.build();
HttpPost httpPost = new HttpPost(URL);
httpPost.setConfig(requestConfig);
Femiが提案したとおり、正常に動作します。ありがとう!
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
if(getMethod != null) {
getMethod.abort();
}
}
}, timeout * 1000);
他の答えを基に、私の解決策は、HttpRequestInterceptor
を使用して、すべてのリクエストにアボート実行可能ファイルを追加することでした。また、Timer
をScheduledExecutorService
に交換しました。
public class TimeoutInterceptor implements HttpRequestInterceptor {
private int requestTimeout = 1 * DateTimeConstants.MILLIS_PER_MINUTE;
private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
public TimeoutInterceptor() { }
public TimeoutInterceptor(final int requestTimeout) {
this.requestTimeout = requestTimeout;
}
@Override
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
if (request instanceof AbstractExecutionAwareRequest) {
final AbstractExecutionAwareRequest abortableRequest = (AbstractExecutionAwareRequest) request;
setAbort(abortableRequest);
} else if (request instanceof HttpRequestWrapper) {
HttpRequestWrapper wrapper = (HttpRequestWrapper) request;
this.process(wrapper.getOriginal(), context);
}
}
/**
* @param abortableRequest
*/
private void setAbort(final AbstractExecutionAwareRequest abortableRequest) {
final SoftReference<AbstractExecutionAwareRequest> requestRef = new SoftReference<AbstractExecutionAwareRequest>(abortableRequest);
executorService.schedule(new Runnable() {
@Override
public void run() {
AbstractExecutionAwareRequest actual = requestRef.get();
if (actual != null && !actual.isAborted()) {
actual.abort();
}
}
}, requestTimeout, TimeUnit.MILLISECONDS);
}
public void setRequestTimeout(final int requestTimeout) {
this.requestTimeout = requestTimeout;
}
}
タイマーは悪です。リクエストごとにスレッド/実行可能オブジェクトを作成するタイマーまたはエグゼキューターまたはその他のメカニズムを使用することは、非常に悪い考えです。賢明に考えて、それをしないでください。そうしないと、実際の環境が多かれ少なかれ、メモリの問題がすぐに発生します。私が提案するソリューションは、1つのウォッチドッグスレッドのみを必要とし、リソースの時間と神経を節約します。基本的には、3つのステップを実行します。 1.リクエストをキャッシュに入れる2.完了時にリクエストをキャッシュから削除する3.制限内で完了していないリクエストを中止する
キャッシュとウォッチドッグスレッドは次のようになります。
import org.Apache.http.client.methods.*;
import Java.util.*;
import Java.util.concurrent.*;
import Java.util.stream.*;
public class RequestCache {
private static final long expireInMillis = 300000;
private static final Map<HttpUriRequest, Long> cache = new ConcurrentHashMap<>();
private static final ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
static {
// run clean up every N minutes
exe.schedule(RequestCache::cleanup, 1, TimeUnit.MINUTES);
}
public static void put(HttpUriRequest request) {
cache.put(request, System.currentTimeMillis());
}
public static void remove(HttpUriRequest request) {
cache.remove(request);
}
private static void cleanup() {
// find expired requests
List<HttpUriRequest> expired = cache.entrySet().stream()
.filter(e -> (System.currentTimeMillis() - e.getValue()) > expireInMillis)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
// abort requests
expired.forEach(r -> {
if (!r.isAborted()) {
r.abort();
}
cache.remove(r);
});
}
}
および次のSudoコードのキャッシュの使用方法
import org.Apache.http.client.methods.*;
public class RequestSample {
public void processRequest() {
HttpUriRequest req = null;
try {
req = createRequest();
RequestCache.put(req);
execute(req);
} finally {
RequestCache.remove(req);
}
}
}
HttpClient 4.3バージョンでは、以下の例を使用できます。5秒間言います
int timeout = 5;
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
HttpClientBuilder.create().setDefaultRequestConfig(config).build();
HttpGet request = new HttpGet("http://localhost:8080/service"); // GET Request
response = client.execute(request);