HttpClient pend sur socketRead0 avec une méthode exécutée avec succès
dans notre application web, un utilisateur peut soumettre une url. Nous allons récupérer les données et analyser le côté serveur. Pour chaque requête, nous utilisons un HttpClient avec les paramètres (pertinents) suivants:
connectionManager.getParams().setConnectionTimeout(10000);
connectionManager.getParams().setSoTimeout(10000);
quand J'appelle HttpMethod.le code d'État a déjà été vérifié pour être acceptable. À ce point le fil est suspendu avec cette trace de pile:
java.net.SocketInputStream.socketRead0 ( native code )
java.net.SocketInputStream.read ( SocketInputStream.java:150 )
java.net.SocketInputStream.read ( SocketInputStream.java:121 )
java.io.BufferedInputStream.read1 ( BufferedInputStream.java:273 )
java.io.BufferedInputStream.read ( BufferedInputStream.java:334 )
java.io.FilterInputStream.read ( FilterInputStream.java:133 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:108 )
java.io.FilterInputStream.read ( FilterInputStream.java:107 )
org.apache.commons.httpclient.AutoCloseInputStream.read ( AutoCloseInputStream.java:127 )
org.apache.commons.httpclient.HttpMethodBase.getResponseBody ( HttpMethodBase.java:690 )
Je ne peux pas trouver L'URL exacte pour laquelle cela s'est produit (était un incident sur un environnement réel) et j'ai été incapable de le reproduire. J'aimerais penser qu'il s'agit simplement du serveur auquel nous nous connectons et qui se comporte étrangement, mais peut-être que je manque quelque chose. Dans les deux cas, y a-t-il un moyen pour moi d'empêcher l'appel de la méthode de blocage d'attendre éternellement? Le SoTimeout est aussi le socket read timeout? Y a-t-il un autre décor qui me manque?
5 réponses
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.
quand J'appelle HttpMethod.le code d'État a déjà été vérifié pour être acceptable. À ce point le fil pend
on dirait que vous avez un problème avec la synchronisation des appels ... vous devez vous assurer que la méthode
HttpMethod.get respondebody
est appelé séquentiellement ou devrait utiliser un mutex (sémaphore ) pour la partie qui change le code d'état
vous devez également diminuer votre limite de temps pour prévenir les pendaisons.
nous voyons cela de manière cohérente dans notre implémentation et il semble que le client http ne gère pas correctement les mauvais serveurs ou quelque chose et qu'il ne chronomètre pas.....Je peux me reproduire dans notre environnement avec ce projet de base de données open source et la trace de la pile est un peu différente...
SocketInputStream.socketRead0 (FileDescriptor, byte[], int, int, int) ligne: non disponible [méthode native]
SocketInputStream.lire (octet[], int, int) ligne: 129
SocketInputBuffer (AbstractSessionInputBuffer).fillBuffer () line: 166
SocketInputBuffer.ligne fillBuffer (): 90
SocketInputBuffer (AbstractSessionInputBuffer).ligne readLine (CharArrayBuffer): 281
DefaultHttpResponseParser.parseHead (SessionInputBuffer) ligne: 92
DefaultHttpResponseParser.parseHead (SessionInputBuffer) ligne: 62
DefaultHttpResponseParser (AbstractMessageParser).parse() de la ligne: 254
DefaultClientConnection (Abstractthttpclientconnection).receiveResponseHeader () ligne: 289
DefaultClientConnection.receiveResponseHeader () line: 252
BasicPooledConnAdapter (AbstractClientConnAdapter).receiveResponseHeader () ligne: 219
HttpRequestExecutor.doReceiveResponse (HttpRequest, HttpClientConnection, HttpContext) ligne: 300
HttpRequestExecutor.exécuter (HttpRequest, HttpClientConnection, HttpContext) line: 127
DefaultRequestDirector.ligne tryExecute(RoutedRequest, HttpContext): 712
DefaultRequestDirector.exécution (HttpHost, HttpRequest, HttpContext) ligne: 517
DefaultHttpClient (AbstractHttpClient).exécution de la ligne (HttpHost, HttpRequest, HttpContext): 906
DefaultHttpClient (AbstractHttpClient).exécution (HttpUriRequest, HttpContext) ligne: 805
ReadAggregations.processAggregation(String, Compteur, compteur, compteur, Compteur) en ligne: 153
ReadAggregations.start() de la ligne: 96
ReadAggregations.ligne principale (String []): 70
vous pouvez essayer d'annuler la requête avec HttpUriRequest#abort (), voir https://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/org/apache/http/client/methods/HttpUriRequest.html#abort%28%29 . Cependant, mettre un timemout qui ne nécessite aucune interception serait plus agréable. Voici une question connexe: fixer le temps dans le client http apache
HttpClient distingue entre connexion et requête. setSoTimeout
va configurer le délai d'expiration du socket de connexion tandis que setConnectionTimeout
va configurer à la fois le délai d'expiration pour le gestionnaire de connexion (combien de temps pour attendre une connexion) et pour l'établissement de la connexion elle-même. Dans le code que vous avez fourni, vous ne définissez pas de délai pour la socket utilisée pour la requête elle-même, et malheureusement, HttpClient n'a pas de délai par défaut pour cela.
comment je fais en v4.4.1:
// 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);