Запит клієнта Java HTTP із визначеним часом очікування


91

Я хотів би зробити 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("");
 }
}

- EDIT: Уточнити, яка бібліотека використовується -

Я використовую 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
HttpClient від Apache має два окремі тайм-аути: тайм-аут на час очікування встановлення TCP-з'єднання та окремий тайм-аут на час очікування наступного байта даних. HttpConnectionParams.setConnectionTimeout () - перший, HttpConnectionParams.setSoTimeout () - другий.
benvolioT

7
Який тайм-аут за замовчуванням? Це 0 = нескінченно?
Тобія

1
http.connection.timeout Integer Час очікування до встановлення з'єднання. Нульове значення означає, що час очікування не використовується.
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. Крім того, чи означає "за замовчуванням", що це за замовчуванням для всього, HttpClientщо HttpClientBuilderдасть build()метод from create () ? Або просто ті, що проходять через setDefaultRequestConfig(requestConfig)? Я маю сенс?
ADTC

@ADTC Ваше питання трохи заплутане :). Конфігурація запиту за замовчуванням буде використана для всіх екземплярів HttpPost, HttpGet, ..., використовуючи "тільки", що HttpClient. Якщо ви зробили інший екземпляр HttpClient, тоді ця конфігурація запиту не використовуватиметься з цим клієнтом.
Грім

35

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

Я пропоную використовувати RequestConfig замість цього на своєму екземплярі HttpGet або HttpPost:

final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);

"використання коду вище" << 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;
}

2
Це не вплине на час очікування для клієнта Apache HTTP.
laz

9
Ніколи не стверджував, що так;)
dbyrne

5
Поняття тайм-ауту HttpURLConnection недостатнє. Якщо сервер починає реагувати, але потім зависає, час очікування ніколи не досягається. HttpClient від Apache - кращий вибір через цю різницю.
benvolioT

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

Про це вже згадувалося у коментарі бенволіота вище. Але, я думаю, це варто посади найвищого рівня, бо це, безсумнівно, змусило мене почухати голову. Я публікую це на випадок, якщо це допоможе комусь іншому.

Я написав простий тестовий клієнт і 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

Пізніше Op заявив, що вони використовують Apache Commons HttpClient 3.0.1

 HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        client.getHttpConnectionManager().getParams().setSoTimeout(5000);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.