Délai d’attente HttpClient

Délai d'attente du client

1. Vue d'ensemble

Ce tutoriel montrera commentconfigure a timeout with the Apache HttpClient 4.

Si vous voulez approfondir et apprendre d'autres choses intéressantes que vous pouvez faire avec HttpClient, rendez-vous surthe main HttpClient tutorial.

Lectures complémentaires:

Gestion de la connexion HttpClient

Comment ouvrir, gérer et fermer des connexions avec Apache HttpClient 4.

Read more

HttpClient 4 - Suivez les redirections pour le POST

Comment activer POST Redirect avec Apache HttpClient.

Read more

Configuration avancée du client

Configurations HttpClient pour les cas d'utilisation avancés.

Read more

2. Configurer les délais via les paramètresString bruts

LeHttpClient est livré avec de nombreux paramètres de configuration, et tous peuvent être définis de manière générique, semblable à une carte.

Il y a3 timeout parameters to configure:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

3. Configurer les délais via l'API

Les plus importants de ces paramètres, à savoir les deux premiers, peuvent également être définis via une API plus sécurisée pour le type:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout

Le troisième paramètre n'a pas de setter personnalisé dansHttpConnectionParams, et il devra toujours être défini manuellement via la méthodesetParameter.

4. Configurer les délais avec la nouvelle version 4.3. Constructeur

L'API de création fluide introduite dans la version 4.3 fournit desthe right way to set timeouts at a high level:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

C'est la méthode recommandée pour configurer les trois délais d'expiration d'une manière sûre et lisible.

5. Explication des propriétés de temporisation

Voyons maintenant ce que signifient ces différents types de délais d'expiration:

  • leConnection Timeout (http.connection.timeout) - l'heure pour établir la connexion avec l'hôte distant

  • leSocket Timeout (http.socket.timeout) - le temps d'attente des données - après l'établissement de la connexion; temps maximal d'inactivité entre deux paquets de données

  • lesConnection Manager Timeout (http.connection-manager.timeout) - le temps d'attente pour une connexion depuis le gestionnaire de connexions / pool

Les deux premiers paramètres - les délais de connexion et de socket - sont les plus importants. Cependant, définir un délai pour obtenir une connexion est certainement important dans les scénarios de charge élevée, c'est pourquoi le troisième paramètre ne doit pas être ignoré.

6. Utilisation desHttpClient

Après l'avoir configuré, nous pouvons maintenant utiliser le client pour effectuer des requêtes HTTP:

HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Avec le client précédemment défini,the connection to the host will time out in 5 seconds. De plus, si la connexion est établie mais qu'aucune donnée n'est reçue, le délai d'expiration sera également de5 additional seconds.

Notez que le délai d'expiration de la connexion entraînera la levée d'unorg.apache.http.conn.ConnectTimeoutException, tandis que le délai d'expiration du socket entraînera unjava.net.SocketTimeoutException.

7. Délai d'attente difficile

Bien que définir des délais d'expiration pour établir la connexion HTTP et ne pas recevoir de données est très utile, nous devons parfois définir unhard timeout for the entire request.

Par exemple, le téléchargement d’un fichier potentiellement volumineux s’inscrit dans cette catégorie. Dans ce cas, la connexion peut être établie avec succès, les données peuvent être transmises de manière cohérente, mais nous devons tout de même nous assurer que l'opération ne dépasse pas un certain seuil de temps.

HttpClient n'a pas de configuration qui nous permet de définir un délai d'expiration global pour une requête; il fournit cependantabort functionality for requests, nous pouvons donc tirer parti de ce mécanisme pour implémenter un mécanisme de timeout simple:

HttpGet getMethod = new HttpGet(
  "http://localhost:8080/httpclient-simple/api/bars/1");

int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);

HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Nous utilisons lesjava.util.Timer etjava.util.TimerTask pour configurer unsimple delayed task which aborts the HTTP GET request après un délai d'attente de 5 secondes.

8. Timeout et DNS Round Robin - quelque chose dont il faut être conscient

Il est assez courant que certains domaines plus importants utilisent une configuration DNS round robin - ayant essentiellementthe same domain mapped to multiple IP addresses. Cela introduit un nouveau défi pour un délai d'expiration par rapport à un tel domaine, tout simplement en raison de la façon dont HttpClient essaiera de se connecter à ce domaine qui expire:

  • HttpClient obtientthe list of IP routes dans ce domaine

  • il essaiethe first one - qui expire (avec les délais que nous configurons)

  • il essaiethe second one - qui expire également

  • etc …

Donc, comme vous pouvez le voir -the overall operation will not time out when we expect it to. Au lieu de cela, il expire lorsque tous les itinéraires possibles ont expiré. De plus, cela se produira de manière totalement transparente pour le client (sauf si vous avez configuré votre journal au niveau DEBUG).

Voici un exemple simple que vous pouvez exécuter et reproduire ce problème:

int timeout = 3;
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://www.google.com:81");
response = client.execute(request);

Vous remarquerez la logique de nouvelle tentative avec un niveau de journal DEBUG:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...

9. Conclusion

Ce didacticiel a expliqué comment configurer les différents types de délais d'expiration disponibles pour unHttpClient. Il a également illustré un mécanisme simple pour le dépassement de délai d'une connexion HTTP en cours.

L'implémentation de ces exemples peut être trouvée dansthe GitHub project.