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.
HttpClient 4 - Suivez les redirections pour le POST
Comment activer POST Redirect avec Apache HttpClient.
Configuration avancée du client
Configurations HttpClient pour les cas d'utilisation avancés.
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.