Апач ожидания с помощью HttpClient
Есть ли способ указать тайм-аут для всего выполнения 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);
На самом деле это работает нормально, за исключением того, что если удаленный хост отправляет обратно данные - даже в один байт/секунду - он будет продолжать читать вечно! Но я хочу прервать соединение максимум через 10 секунд, независимо от того, ответит ли хост.
6 ответов:
В настоящее время нет способа установить максимальную длительность запроса такого рода: в основном вы хотите сказать мне все равно, истекает ли какой-либо конкретный этап запроса, но весь запрос не должен длиться дольше 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);
В 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);
Отталкиваясь от других ответов, мое решение состояло в том, чтобы использовать
HttpRequestInterceptor
, чтобы добавить abort runnable к каждому запросу. Также я поменял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; } }