Demande de client HTTP Java avec délai d'expiration défini

92

Je voudrais faire des BIT (Built in tests) sur un certain nombre de serveurs dans mon cloud. J'ai besoin que la demande échoue sur un délai d'attente important.

Comment dois-je faire cela avec java?

Essayer quelque chose comme ci-dessous ne semble pas fonctionner.

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: clarifier quelle bibliothèque est utilisée -

J'utilise httpclient d'Apache, voici la section pom.xml correspondante

 <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.0.1</version>
   <type>jar</type>
 </dependency>
Maxim Veksler
la source
Quelle bibliothèque utilisez-vous pour toutes les fonctionnalités HTTP?
nojo
Merci pour le commentaire. J'ai mis à jour mon message.
Maxim Veksler

Réponses:

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);
laz
la source
1
Qu'est-ce que cela fait? Un délai d'expiration de ce qu'il définit? Veuillez consulter stackoverflow.com/questions/3000767/…
Maxim Veksler
84
Le HttpClient d'Apache a deux délais d'expiration distincts: un délai d'attente pour établir une connexion TCP et un délai d'attente distinct pour la durée d'attente d'un octet de données suivant. HttpConnectionParams.setConnectionTimeout () est le premier, HttpConnectionParams.setSoTimeout () est le dernier.
benvolioT
7
Quel est le délai d'expiration par défaut? Est-ce 0 = infini?
Tobia
1
http.connection.timeout Entier Délai d'attente jusqu'à l'établissement d'une connexion. Une valeur de zéro signifie que le délai n'est pas utilisé.
maveroid
26
Pour les futurs lecteurs: il convient de noter que les classes référencées ici sont désormais obsolètes (à partir du 05/07/2016), bien que ce soit probablement une bonne réponse lors de sa publication en 2010. Voir cette réponse: stackoverflow.com/a/ 19153314/192801 pour quelque chose d'un peu plus actuel.
FrustratedWithFormsDesigner
125

Si vous utilisez Http Client version 4.3 et supérieure, vous devriez utiliser ceci:

RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build();
HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
Tonnerre
la source
4
Merci! J'ai passé au moins 20 minutes à essayer de comprendre comment se débarrasser des commandes obsolètes pour le faire avant de trouver votre réponse.
vextorspace
Oublié SocketTimeout. Aussi, "default" signifie-t-il que c'est par défaut pour tout ce HttpClientque la méthode HttpClientBuilderfrom create () donnera via build()? Ou juste ceux qui passent setDefaultRequestConfig(requestConfig)? Ai-je un sens?
ADTC
@ADTC Votre question est un peu déroutante :). La configuration de requête par défaut sera utilisée pour toutes les instances HttpPost, HttpGet, ... utilisant «uniquement» ce HttpClient. Si vous avez créé une autre instance HttpClient, cette configuration de demande ne sera pas utilisée avec ce client.
Thunder
35

HttpParams est obsolète dans la nouvelle bibliothèque Apache HTTPClient. L'utilisation du code fourni par Laz entraîne des avertissements d'obsolescence.

Je suggère d'utiliser RequestConfig à la place sur votre instance HttpGet ou HttpPost:

final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build();
httpPost.setConfig(params);
pmartin8
la source
"en utilisant le code ci-dessus" << SO n'est pas un forum et les réponses montent / descendent en raison de plusieurs facteurs, nous ne savons donc pas à quel code vous faites référence. Pourriez-vous dire quelque chose comme "en utilisant le code de la réponse de xyz"?
ADTC
4
Btw, bonne réponse. Mais par rapport à la réponse de Thunder, quelle est la différence entre définir le RequestConfigdans chaque HttpPostpar opposition à le définir par défaut dans le HttpClient?
ADTC
2
Oui, vous avez raison, le code ci-dessus fait référence à la "réponse acceptée" qui ne devrait pas changer avec le temps. Je
mettrai à
10

Il semble que vous utilisez l'API HttpClient, dont je ne sais rien, mais vous pouvez écrire quelque chose de similaire en utilisant le noyau 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
la source
2
Cela n'affectera pas le délai d'expiration du client HTTP Apache.
laz
9
Je ne l'ai jamais prétendu;)
dbyrne
5
La notion de timeout de HttpURLConnection est insuffisante. Si le serveur commence à répondre, mais se bloque ensuite, le délai d'attente n'est jamais atteint. HttpClient d'Apache est un meilleur choix en raison de cette différence.
benvolioT
7

J'ai trouvé que le réglage des paramètres de temporisation dans HttpConnectionParamsetHttpConnectionManager n'a pas résolu notre cas. Nous sommes limités à l'utilisation de la org.apache.commons.httpclientversion 3.0.1.

J'ai fini par utiliser un java.util.concurrent.ExecutorService pour surveiller l' HttpClient.executeMethod()appel.

Voici un petit exemple autonome

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);
      }
   }
}
Kirby
la source
7

La méthode dite avec les plus hauts de Laz est obsolète à partir de la version 4.3. Par conséquent, il serait préférable d'utiliser l'objet Request Config, puis de créer le client 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 permet à l'utilisateur de définir le nombre maximal de connexions par défaut et le nombre maximal de connexions par route. Je l'ai défini comme 306 et 108 respectivement. Les valeurs par défaut ne seront pas suffisantes dans la plupart des cas.

Pour définir le délai d'expiration: j'ai utilisé l'objet RequestConfig. Vous pouvez également définir la propriété Délai de demande de connexion pour définir le délai d'attente de connexion à partir du Gestionnaire de connexions.

Arun Thundyill Saseendran
la source
5

Cela a déjà été mentionné dans un commentaire de benvoliot ci-dessus. Mais je pense que cela vaut la peine d'un article de haut niveau, car cela m'a certainement fait me gratter la tête. Je poste ceci au cas où cela aiderait quelqu'un d'autre.

J'ai écrit un client de test simple et le CoreConnectionPNames.CONNECTION_TIMEOUTdélai d'attente fonctionne parfaitement dans ce cas. La demande est annulée si le serveur ne répond pas.

À l'intérieur du code serveur, j'essayais en fait de tester, cependant, le code identique n'expire jamais.

Changer le délai d'expiration de l'activité de connexion socket ( CoreConnectionPNames.SO_TIMEOUT) plutôt que de la connexion HTTP ( CoreConnectionPNames.CONNECTION_TIMEOUT) a résolu le problème pour moi.

Lisez également attentivement la documentation Apache: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT

Notez le peu qui dit

Veuillez noter que ce paramètre ne peut être appliqué qu'aux connexions liées à une adresse locale particulière.

J'espère que cela épargnera à quelqu'un d'autre tous les griffures que j'ai subies. Cela m'apprendra à ne pas lire attentivement la documentation!

Dan Haynes
la source
2

Op a déclaré plus tard qu'ils utilisaient Apache Commons HttpClient 3.0.1

 HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        client.getHttpConnectionManager().getParams().setSoTimeout(5000);
rtaft
la source
1

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

Vous pouvez également définir votre délai d'attente requis.

Mohammed Irfan Tirupattur
la source