40 votes

En utilisant Apache HttpClient, comment définir le délai d'attente (TIMEOUT) d'une requête et d'une réponse ?

J'ai besoin de définir un délai pour les requêtes Http que nous faisons à un service (pas un service web). Nous utilisons le client HTTP Apache. J'ai ajouté ces deux lignes de code pour définir le délai d'attente sur la requête et la réponse au service.

HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);

1) Actuellement, j'ai fixé le délai d'attente à 10 secondes, car la réponse du service est presque instantanée. Dois-je augmenter ou réduire le délai ?

2) Que se passe-t-il lorsque la réponse prend plus de 10 secondes ? Lancera-t-il une exception et de quelle exception s'agira-t-il ? Y a-t-il quelque chose d'autre que je doive ajouter pour définir le délai dans le code ci-dessous.

public HashMap<String, Object> getJSONData(String url) throw Exception{
    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpParams params = httpClient.getParams();
    HttpConnectionParams.setConnectionTimeout(params, 10000);
    HttpConnectionParams.setSoTimeout(params, 10000);
    HttpHost proxy = new HttpHost(getProxy(), getProxyPort());
    ConnRouteParams.setDefaultProxy(params, proxy);
    URI uri;
    InputStream data = null;
    try {
        uri = new URI(url);
        HttpGet method = new HttpGet(uri);
        HttpResponse response = httpClient.execute(method);
        data = response.getEntity().getContent();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    Reader r = new InputStreamReader(data);
    HashMap<String, Object> jsonObj = (HashMap<String, Object>) GenericJSONUtil.fromJson(r);
    return jsonObj;
}

75voto

simao Points 2906

Je suppose que beaucoup de gens viennent ici à cause du titre et parce que la HttpConnectionParams est obsolète.

En utilisant une version récente du client HTTP Apache, vous pouvez définir ces délais en utilisant les paramètres de la requête :

HttpPost request = new HttpPost(url);

RequestConfig requestConfig = RequestConfig.custom()
  .setSocketTimeout(TIMEOUT_MILLIS)
  .setConnectTimeout(TIMEOUT_MILLIS)
  .setConnectionRequestTimeout(TIMEOUT_MILLIS)
  .build();

request.setConfig(requestConfig);

Vous pouvez également définir ce paramètre lorsque vous créez votre client HTTP, en utilisant l'API de construction pour le client HTTP, mais vous devrez également créer un gestionnaire de connexion personnalisé avec une configuration de socket personnalisée.

En fichier d'exemple de configuration est une excellente ressource pour savoir comment configurer le client HTTP Apache.

36voto

Kevin Points 10204

Les exceptions que vous verrez sont les suivantes ConnectTimeoutException y SocketTimeoutException . Les valeurs de délai d'attente que vous utilisez doivent correspondre au temps maximum que votre application est prête à attendre. Une remarque importante à propos du délai de lecture est qu'il correspond au délai de lecture d'une socket. Il ne s'agit donc pas du temps alloué à l'arrivée de la réponse complète, mais plutôt du temps accordé à la lecture d'une seule socket. Ainsi, s'il y a 4 lectures de socket, chacune prenant 9 secondes, votre temps de lecture total est de 9 * 4 = 36 secondes.

Si vous voulez spécifier un temps total pour que la réponse arrive (y compris le temps de connexion et le temps de lecture total), vous pouvez envelopper l'appel dans un thread et utiliser un timeout de thread pour cela. Par exemple, je fais habituellement quelque chose comme ceci :

Future<T> future = null;
future = pool.submit(new Callable<T>() {
    public T call() {
        return executeImpl(url);
    }   
}); 

try {
    return future.get(10, TimeUnit.SECONDS);
}   
catch (InterruptedException e) {
    log.warn("task interrupted", name);
}   
catch (ExecutionException e) {
    log.error(name + " execution exception", e); 
}   
catch (TimeoutException e) {
    log.debug("future timed out", name);
}

Le code ci-dessus repose sur les hypothèses suivantes : 1) ceci est dans une fonction avec un paramètre url, 2) c'est dans une classe avec une variable nom, 3) log est une instance de log4j, et 4) pool est un certain exécuteur de pool de threads. Notez que même si vous utilisez un thread timeout, vous devez également spécifier un connect and socket timeout sur le HttpClient, afin que les requêtes lentes ne consomment pas les ressources du thread pool. Notez également que j'utilise un pool de threads parce que je l'utilise généralement dans un service web, de sorte que le pool de threads est partagé entre plusieurs threads de Tomcat. Votre environnement peut être différent, et vous pouvez préférer simplement créer un nouveau thread pour chaque appel.

De plus, j'ai généralement vu les délais fixés par des fonctions membres des paramètres, comme ceci :

params.setConnectionTimeout(10000);
params.setSoTimeout(10000);

Mais peut-être que votre syntaxe fonctionne également (je n'en suis pas sûr).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X