web-dev-qa-db-fra.com

Httpclient coincé sans aucune exception

Je développe une application à long terme qui utilise fortement le httpclient d'Apache.

Lors de mon premier test, l'application a parfaitement fonctionné jusqu'à ce qu'il reste coincé. Il n'a pas été arrêté, il n'a pas lancé d'exception, il est juste assis à ne rien faire.

J'ai fait une deuxième course juste maintenant et arrêté le temps et il s'est arrêté après env. 24 heures de conant en cours d'exécution. De plus, j'ai remarqué que la connexion Internet de mon ordinateur portable sur lequel je l'avais fait courir était terminée au moment précis que la demande a été bloquée. J'ai dû redémarrer mon adaptateur WLAN pour que le réseau soit à nouveau opérationnel.

L'application, cependant, ne revenait pas à travailler après la réalisation de la connexion. Et maintenant, il est encore bloqué.

Y a-t-il un contrôleur de délai d'expiration que je ne suis pas au courant dans le httpclient? Pourquoi mon application ne jette-t-elle pas une exception lorsque la connexion est en panne?

La partie qui utilise le client semble comme suit;

public HttpUtil(ConfigUtil config) {
    this.config = config;

    client = new DefaultHttpClient();
    client.getParams().setParameter(HttpProtocolParams.USER_AGENT, this.config.getProperty("httputil.userAgent"));
}

public String getContentAsString(String url) throws ParseException, ClientProtocolException, IOException {
    return EntityUtils.toString(
            client.execute(
                    new HttpGet(url)).getEntity());
}

L'application appelle à plusieurs reprises httputil.getContentAsString() sur les URL dont il a besoin.

25
F.P

À partir de la version 4.4, les deux réponses des utilisateurs User2393012 et Stephen C ont été obsolètes. Je ne suis pas sûr que s'il y a une autre façon de le faire, mais la façon dont je le fais est en utilisant un paradigme de constructeur, httpclientbuilder.

Ex.

HttpClients.custom().setConnectionTimeToLive(1, TimeUnit.MINUTES).build()

Un problème très similaire (il aurait peut-être pu être le problème de l'OP) à quel point mentionné peut également se produire, mais est dû à Apache définissant les connexions simultanées par défaut à seulement deux connexions par client. La solution pour cela serait d'augmenter les connexions maximales ou de les fermer si vous le pouvez.

Pour augmenter les connexions max:

HttpClients.custom().setMaxConnPerRoute(100000).build()

Pour fermer les connexions, vous pouvez utiliser un BasichttpClientConnectionManager et appeler la méthode de fermeture pour

8
Muhatashim

Vous n'avez pas dit quelle version de httpclient vous utilisez, mais en supposant que c'est la version 4, Cet article de blog explique quoi faire.

DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis);
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis);
6
Stephen C

J'ai donné une réponse similaire dans un autre thread ( httpClient se bloque sur SockeTread0 avec méthode exécutée avec succès )

Dans mon cas, je définissais le ConnectionTimeOut et Sockettimeout sur la demande, mais pas sur la prise de connexion utilisée lors de l'établissement de la connexion SSL. En conséquence, je voudrais parfois accrocher pendant la poignée de main SSL. Vous trouverez ci-dessous un code qui définit tous les 3 délais d'attente à l'aide du V4.4 (également testé dans V4.5)

// Configure the socket timeout for the connection, incl. ssl tunneling
connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(200);
connManager.setDefaultMaxPerRoute(100);

SocketConfig sc = SocketConfig.custom()
    .setSoTimeout(soTimeoutMs)
    .build();

connManager.setDefaultSocketConfig(sc);

HttpClient client = HttpClients.custom()
            .setConnectionManager(connManager)
            .setConnectionManagerShared(true)
            .build();

// configure the timeouts (socket and connection) for the request
RequestConfig.Builder config = = RequestConfig.copy(RequestConfig.DEFAULT);
config.setConnectionRequestTimeout(connectionTimeoutMs);
config.setSocketTimeout(socketTimeoutMs);

HttpRequestBase req = new HttpGet(uri);
req.setConfig(config.build());

client.execute(req);
5
GaspardP

J'ai toutes les délais d'attente d'expression juste bien mais j'ai découvert que nous avons sur l'URL qui fait des chunks http mais n'envoie aucun résultat (fonctionne bien en chrome, mais dans le client HTTP, il est suspendu à jamais, même avec le délai d'attente). Heureusement, je possède le serveur et je viens de retourner quelques ordures et il ne se bloque plus. Cela semble être un bogue très unique dans ce client HTTP ne gère pas bien une sorte de fond de chunking vide (bien que je puisse passer à pied) ... Je sais juste que cela pend à chaque fois sur cette même URL avec des données vides et cette URL Est-ce que http chunking csv téléchargez-vous sur notre client HTTP.

4
Dean Hiller

J'ai eu le même problème, il a coincé parce que je n'ai pas fermé defaulthttpclient.
[.____] Alors c'est faux:

try{
    DefaultHttpClient httpclient = new DefaultHttpClient();
    ...
} catch (Exception e){
    e.PrintStackTrace();
}

Et c'est vrai:

try (DefaultHttpClient httpclient = new DefaultHttpClient()){
    ...
} catch (Exception e){
    e.PrintStackTrace();
}

J'espère que cela aide quelqu'un.

4
Max Husiv

Par défaut, httpClient n'empêche pas (ce qui provoque un plus de problème que ce qu'il aide). Ce que vous décrivez pourrait être une question matérielle, si votre adaptateur réseau est mort, le HTTPCLIPT sera suspendu.

Voici les paramètres défini sur httpparams dans le cadre du constructeur à défaulthttpclient y compris

http.socket.timeout : Définit le délai d'attente de socket (SO_TIMEOUT) en millisecondes, qui est le délai d'attente pour attendre des données ou, mis différemment, une période maximale inactivité entre deux paquets de données consécutifs). Une valeur d'expiration de zéro est interprétée comme un délai d'attente infini. Ce paramètre attend une valeur de type java.lang.Integer. Si ce paramètre n'est pas défini, les opérations de lecture ne seront pas tirées (délai d'attente infini).

Cela définira un délai d'attente sur la connexion, de sorte qu'une fois le délai défini, une exception sera lancée.

3
mguymon