Apache HttpClient timeout - PullRequest
       39

Apache HttpClient timeout

50 голосов
/ 20 июля 2011

Есть ли способ указать время ожидания для всего выполнения 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 секунд, независимо от того, отвечает хост или нет.

Ответы [ 7 ]

55 голосов
/ 12 апреля 2015

Для более новой версии httpclient (например, компоненты http 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);
30 голосов
/ 20 июля 2011

В настоящее время нет способа установить максимальную длительность запроса такого рода: в основном вы хотите сказать Мне все равно, истечет ли какой-либо конкретный запрос время ожидания, но весь запрос не должен длиться дольше 15 секунд (например).

Лучше всего было бы запустить отдельный таймер, а по истечении этого срока извлечь менеджер соединений, используемый экземпляром HttpClient, и завершить соединение, что должно прервать соединение. Дайте мне знать, если это работает для вас.

14 голосов
/ 21 июля 2011

Работает нормально, как предложено Феми. Спасибо!

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    public void run() {
        if(getMethod != null) {
            getMethod.abort();
        }
    }
}, timeout * 1000);
3 голосов
/ 23 мая 2016

Основываясь на других ответах, я решил использовать 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 голос
/ 18 апреля 2019

Таймер это зло.Использование таймера или исполнителя или любого другого механизма, который создает поток / запускаемый объект для запроса, очень плохая идея.Пожалуйста, подумайте мудро и не делайте этого.В противном случае вы быстро столкнетесь с проблемами памяти в более или менее реальной среде.Решение, которое я предлагаю, потребует только 1 сторожевой поток и сэкономит вам ресурсы времени и нервов.В основном вы делаете 3 шага.1. поместите запрос в кеш 2. удалите запрос из кеша по завершении 3. прервите запросы, которые не завершены в рамках вашего лимита

ваш кэш вместе с потоком сторожевого таймера может выглядеть следующим образом.* и следующий код 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);
    }
  }
}
1 голос
/ 19 августа 2014

В версии 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);
0 голосов
/ 22 августа 2013

Это тоже работа:

HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), timeout * 1000);
HttpConnectionParams.setSoTimeout(client.getParams(), timeout * 1000);
...