web-dev-qa-db-fra.com

Utilisation d'Apache HttpClient pour définir le TIMEOUT sur une demande et une réponse

J'ai besoin de définir un délai pour la demande Http que nous faisons à un service (pas un service Web). Nous utilisons Apache HTTP Client. J'ai ajouté ces 2 lignes de code pour définir le délai d'attente sur demande et la réponse au service.

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

1) Actuellement, j'ai défini 10 secondes comme délai d'attente car je vois la réponse provenant du service presque instantanément. Dois-je augmenter ou diminuer le timing?

2) Que se passera-t-il lorsque la réponse prendra plus de 10 secondes? Va-t-elle lever l'exception et quelle sera-t-elle? Y a-t-il autre chose que je dois 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;
}
35
pushya

Les exceptions que vous verrez seront ConnectTimeoutException et SocketTimeoutException. Les valeurs de délai d'attente réelles que vous utilisez doivent être le temps maximum que votre application est prête à attendre. Une remarque importante sur le délai de lecture est qu'il correspond au délai sur une lecture de socket. Ce n'est donc pas le temps imparti pour que la réponse complète arrive, mais plutôt le temps donné à une seule prise de lecture. Donc, 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 souhaitez 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 encapsuler l'appel dans un thread et utiliser un délai 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);
}

Certaines hypothèses faites dans le code ci-dessus sont: 1) c'est dans une fonction avec un paramètre url, 2) c'est dans une classe avec une variable de nom, 3) log est une instance de log4j, et 4) pool est un exécuteur de pool de threads . Notez que même si vous utilisez un délai d'expiration de thread, vous devez également spécifier un délai d'expiration de connexion et de socket sur le HttpClient, afin que les requêtes lentes ne consomment pas les ressources du pool de threads. Notez également que j'utilise un pool de threads, car j'utilise généralement celui-ci dans un service Web afin que le pool de threads soit partagé entre plusieurs threads Tomcat. Votre environnement peut être différent et vous préférerez peut-être simplement générer un nouveau thread pour chaque appel.

En outre, j'ai généralement vu les délais d'attente définis via les fonctions membres des paramètres, comme ceci:

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

Mais peut-être que votre syntaxe fonctionne aussi (pas sûr).

35
Kevin

Je suppose que beaucoup de gens viennent ici à cause du titre et parce que l'API HttpConnectionParams est déconseillée.

À l'aide d'une version récente d'Apache HTTP Client, vous pouvez définir ces délais d'expiration à l'aide des paramètres de demande:

HttpPost request = new HttpPost(url);

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

request.setConfig(requestConfig);

Alternativement, vous pouvez également définir cela lorsque vous créez votre client HTTP, à l'aide de l'API du générateur pour le client HTTP, mais vous devrez également créer un gestionnaire de connexions personnalisé avec une configuration de socket personnalisée.

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

64
simao