HttpClient est resté sans exception
je développe une application de longue durée qui utilise largement le protocole HttpClient d'apache.
Sur mon premier essai, l'application a fonctionné parfaitement jusqu'à ce qu'elle s'est coincé. Il n'a pas été arrêté, il n'a pas fait d'exception, il est juste assis là à ne rien faire.
j'ai fait un deuxième tour tout à l'heure et il s'est arrêté après environ. 24 heures de course contant. En outre, j'ai remarqué que la connexion internet de mon ordinateur portable sur que j'ai fait fonctionner a été terminé au moment où l'application a été bloquée. J'ai dû redémarrer mon adaptateur WLAN pour que le filet tourne à nouveau.
l'application cependant,n'est pas retourné à travailler après la connexion était à nouveau. Et maintenant, elle est encore coincée.
y a-t-il un contrôleur de temps d'arrêt dont je ne suis pas au courant dans le HttpClient? Pourquoi mon application ne lance-t-elle pas une exception quand la connexion est coupée?
le la partie qui utilise le client se présente 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 elle a besoin.
7 réponses
ce code est maintenant déprécié (get HttpParams, etc). Une meilleure façon est:
RequestConfig defaultRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BEST_MATCH).setExpectContinueEnabled(true).setStaleConnectionCheckEnabled(true).setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)).setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig).setSocketTimeout(5000).setConnectTimeout(5000).setConnectionRequestTimeout(5000).build();
httpGet.setConfig(requestConfig);
depuis la version 4.4, les deux réponses des utilisateurs user2393012 et Stephen C ont été dépréciées. Je ne suis pas sûr qu'il y ait 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 pourrait en fait avoir été le problème de OP) à ce que OP a également mentionné mais est dû au fait Qu'Apache a paramétré les connexions simultanées par défaut à seulement deux connexions par client. La solution à cela serait d'augmenter les connexions max 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 gestionnaire de connexion Basichttpclient et faire appel à la méthode close pour
vous n'avez pas dit quelle version de HttpClient vous utilisez, mais en supposant que ce soit la version 4, cet article de blog explique ce qu'il faut faire.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis);
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis);
j'ai donné une réponse similaire dans un autre thread ( HttpClient accroche sur socketRead0 avec méthode exécutée avec succès )
dans mon cas, je réglais le connectionTimeout et le socketTimeout sur la requête, mais pas sur la prise de connexion utilisée lors de l'établissement de la connexion SSL. Par conséquent, je serais parfois pendu pendant la poignée de main SSL. Ci-dessous se trouve un code qui définit les 3 temps d'arrêt en utilisant le v4.4 (également testé en 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);
j'ai toutes les configurations de timeouts très bien mais j'ai découvert que nous avons sur l'url qui fait le chunking http mais n'envoie aucun résultat(fonctionne très bien dans chrome, mais dans le client http il reste à jamais même avec le timeout). Heureusement, je possède le serveur et juste retourner quelques ordures et il ne pend plus. Cela ressemble à un bug très unique dans le fait que le client http ne gère pas bien une sorte de cas vide de chunking(bien que je puisse être loin)....Je sais juste qu'il est accroché à chaque fois sur cette même url avec des données vides et cette url est http chunking csv télécharger à nouveau à notre client http.
par défaut, HttpClient ne fait pas de timeout (ce qui cause plus de problèmes qu'il n'aide). Ce que vous décrivez pourrait être un problème de matériel, si votre adaptateur réseau est mort, le HttpClient sera suspendu.
Voici les paramètres mis à HttpParams comme partie du constructeur à DefaultHttpClient y compris
http.socket.timeouts : définit le timeout de socket (SO_TIMEOUT) dans millisecondes, qui est le délai d'attente pour les données ou, mis autrement, une période maximale d'inactivité entre deux données consécutives paquet.) Une valeur de délai d'expiration de zéro est interprété comme un infini timeouts. Ce paramètre attend une valeur de type java.lang.Entier. Si ce paramètre n'est pas défini, les opérations de lecture n'aura pas le temps (infini timeouts.)
qui mettra un temps d'arrêt sur le connexion, donc après la temporisation, une exception sera levée.
j'ai eu le même problème, il est resté parce que je n'ai pas fermé DefaultHttpClient.
Donc c'est mal:
try{
DefaultHttpClient httpclient = new DefaultHttpClient();
...
} catch (Exception e){
e.PrintStackTrace();
}
Et ce qui est juste:
try (DefaultHttpClient httpclient = new DefaultHttpClient()){
...
} catch (Exception e){
e.PrintStackTrace();
}
J'espère que ça aidera quelqu'un.