Запрос клиента HTTP Java с заданным таймаутом

92

Я хотел бы сделать BIT (встроенные тесты) для ряда серверов в моем облаке. Мне нужно, чтобы запрос завершился ошибкой при большом тайм-ауте.

Как мне сделать это с помощью java?

Попытка сделать что-то подобное ниже, похоже, не работает.

public class TestNodeAliveness {
 public static NodeStatus nodeBIT(String elasticIP) throws ClientProtocolException, IOException {
  HttpClient client = new DefaultHttpClient();
  client.getParams().setIntParameter("http.connection.timeout", 1);

  HttpUriRequest request = new HttpGet("http://192.168.20.43");
  HttpResponse response = client.execute(request);

  System.out.println(response.toString());
  return null;
 }


 public static void main(String[] args) throws ClientProtocolException, IOException {
  nodeBIT("");
 }
}

- РЕДАКТИРОВАТЬ: уточнить, какая библиотека используется -

Я использую httpclient из apache, вот соответствующий раздел pom.xml

 <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.0.1</version>
   <type>jar</type>
 </dependency>
Максим Векслер
источник
Какую библиотеку вы используете для всех функций HTTP?
nojo
Спасибо за комментарий. Я обновил свой пост.
Максим Векслер

Ответы:

119
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

...

    // set the connection timeout value to 30 seconds (30000 milliseconds)
    final HttpParams httpParams = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpParams, 30000);
    client = new DefaultHttpClient(httpParams);
лаз
источник
1
Что это значит? Тайм-аут чего он выставил? См. Stackoverflow.com/questions/3000767/…
Максим Векслер
84
У Apache HttpClient есть два отдельных таймаута: тайм-аут, указывающий, как долго ждать установления TCP-соединения, и отдельный тайм-аут, как долго ждать следующего байта данных. HttpConnectionParams.setConnectionTimeout () - это первое, HttpConnectionParams.setSoTimeout () - второе.
benvolioT 09
7
Какой тайм-аут по умолчанию? 0 = бесконечно?
Tobia
1
http.connection.timeout Целое число Время ожидания до установления соединения. Нулевое значение означает, что тайм-аут не используется.
maveroid
26
Будущим читателям: следует отметить, что упомянутые здесь классы теперь устарели (по состоянию на 05.07.2016), хотя, вероятно, это был хороший ответ, когда он был опубликован в 2010 году. См. Этот ответ: stackoverflow.com/a/ 19153314/192801 для чего-нибудь более современного.
FrustratedWithFormsDesigner
125

Если вы используете Http Client версии 4.3 и выше, вам следует использовать следующее:

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
гром
источник
4
Благодарность! Я потратил по крайней мере 20 минут на то, чтобы понять, как избавиться от устаревших команд, прежде чем найти ваш ответ.
vextorspace
Забыл SocketTimeout. Кроме того, означает ли "default" это значение по умолчанию для всего, HttpClientчто HttpClientBuilderпередаст build()метод from create () ? Или только те, которые проходят setDefaultRequestConfig(requestConfig)? Я понимаю?
ADTC
@ADTC Ваш вопрос немного сбивает с толку :). Конфигурация запроса по умолчанию будет использоваться для всех экземпляров HttpPost, HttpGet, ..., использующих только этот HttpClient. Если вы создали другой экземпляр HttpClient, эта конфигурация запроса не будет использоваться с этим клиентом.
Thunder
35

HttpParams устарел в новой библиотеке Apache HTTPClient. Использование кода, предоставленного Laz, приводит к предупреждению об устаревании.

Я предлагаю вместо этого использовать RequestConfig в вашем экземпляре HttpGet или HttpPost:

final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);
pmartin8
источник
"using the code above" << SO - это не форум, и ответы меняются вверх / вниз из-за нескольких факторов, поэтому мы не знаем, какой код вы имеете в виду. Не могли бы вы сказать что-то вроде «используя код из ответа xyz»?
ADTC
4
Кстати, аккуратный ответ. Но по сравнению с ответом Thunder, в чем разница между установкой RequestConfigв каждый HttpPostи по умолчанию в HttpClient?
ADTC
2
Да, вы правы, приведенный выше код относится к «принятому ответу», который не должен меняться со временем. Я все равно
обновлю
10

Похоже, вы используете HttpClient API, о котором я ничего не знаю, но вы можете написать что-то подобное, используя ядро ​​Java.

try {

   HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
   con.setRequestMethod("HEAD");
   con.setConnectTimeout(5000); //set timeout to 5 seconds
   return (con.getResponseCode() == HttpURLConnection.HTTP_OK);

} catch (java.net.SocketTimeoutException e) {
   return false;
} catch (java.io.IOException e) {
   return false;
}
Dbyrne
источник
2
Это не повлияет на тайм-аут для HTTP-клиента Apache.
laz
9
Никогда не утверждал, что это сделал;)
dbyrne 09
5
Понятие тайм-аута в HttpURLConnection недостаточно. Если сервер начинает отвечать, но затем зависает, таймаут никогда не достигается. HttpClient от Apache - лучший выбор из-за этой разницы.
benvolioT 09
7

Я обнаружил , что установка времени из настроек в HttpConnectionParamsи HttpConnectionManagerне решало наше дело. Мы ограничены использованием org.apache.commons.httpclientверсии 3.0.1.

В итоге я использовал java.util.concurrent.ExecutorServiceдля отслеживания HttpClient.executeMethod()звонка.

Вот небольшой автономный пример

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Jeff Kirby
 * @since <pre>Jun 17, 2011</pre>
 */
public class Example {

   private static final String SITE = "http://some.website.com/upload";
   private static final int TIME_OUT_SECS = 5;

   // upload a file and return the response as a string
   public String post(File file) throws IOException, InterruptedException {
      final Part[] multiPart = { new FilePart("file", file.getName(), file) };
      final EntityEnclosingMethod post = new PostMethod(SITE);
      post.setRequestEntity(new MultipartRequestEntity(multiPart, post.getParams()));
      final ExecutorService executor = Executors.newSingleThreadExecutor();
      final List<Future<Integer>> futures = executor.invokeAll(Arrays.asList(new KillableHttpClient(post)), TIME_OUT_SECS, TimeUnit.SECONDS);
      executor.shutdown();
      if(futures.get(0).isCancelled()) {
         throw new IOException(SITE + " has timed out. It has taken more than " + TIME_OUT_SECS + " seconds to respond");
      }
      return post.getResponseBodyAsString();
   }

   private static class KillableHttpClient implements Callable<Integer> {

      private final EntityEnclosingMethod post;

      private KillableHttpClient(EntityEnclosingMethod post) {
         this.post = post;
      }

      public Integer call() throws Exception {
         return new HttpClient().executeMethod(post);
      }
   }
}
Кирби
источник
7

Указанный метод с наивысшими показателями Laz устарел начиная с версии 4.3. Следовательно, было бы лучше использовать объект конфигурации запроса, а затем создать HTTP-клиент.

    private CloseableHttpClient createHttpClient()
        {
        CloseableHttpClient httpClient;
        CommonHelperFunctions helperFunctions = new CommonHelperFunctions();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(306);
        cm.setDefaultMaxPerRoute(108);
        RequestConfig requestConfig = RequestConfig.custom()
            .setConnectTimeout(15000)
            .setSocketTimeout(15000).build();
        httpClient = HttpClients.custom()
            .setConnectionManager(cm)
            .setDefaultRequestConfig(requestConfig).build();
        return httpClient;
        }

PoolingHttpClientConnectionManager позволяет пользователю установить максимальное количество подключений по умолчанию и максимальное количество подключений на маршрут. Я установил 306 и 108 соответственно. В большинстве случаев значений по умолчанию будет недостаточно.

Для установки тайм-аута: я использовал объект RequestConfig. Вы также можете установить свойство Connection Request Timeout для установки тайм-аута ожидания соединения от диспетчера соединений.

Арун Тандьилл Сасендран
источник
5

Об этом уже упоминалось в комментарии Benvoliot выше. Но я думаю, что это стоит поста на высшем уровне, потому что он наверняка заставил меня почесать голову. Я отправляю это на случай, если это поможет кому-то другому.

Я написал простой тестовый клиент, и CoreConnectionPNames.CONNECTION_TIMEOUTв этом случае тайм-аут отлично работает. Запрос отменяется, если сервер не отвечает.

Однако внутри серверного кода, который я пытался протестировать, время ожидания идентичного кода никогда не истекло.

Изменение его на тайм-аут для активности соединения сокета ( CoreConnectionPNames.SO_TIMEOUT) вместо HTTP-соединения ( CoreConnectionPNames.CONNECTION_TIMEOUT) устранило проблему для меня.

Также внимательно прочтите документы Apache: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

Обратите внимание на бит, который говорит

Обратите внимание, что этот параметр может применяться только к соединениям, привязанным к определенному локальному адресу.

Я надеюсь, что это избавит кого-то от всей моей боли в голове. Это научит меня не читать документацию досконально!

Дэн Хейнс
источник
2

Позже Оп заявил, что они использовали Apache Commons HttpClient 3.0.1.

 HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        client.getHttpConnectionManager().getParams().setSoTimeout(5000);
rtaft
источник
1

HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout

Вы также можете определить требуемый тайм-аут.

Мохаммед Ирфан Тирупаттур
источник