Erreur intermédiaire Apache HttpClient: exception NoHttpResponseException

J’ai un webservice qui accepte une méthode POST avec XML. Il fonctionne correctement, mais à un moment donné, il ne parvient pas à communiquer avec le serveur émettant une exception IOException avec le message The target server failed to respond . Les appels suivants fonctionnent correctement.

Cela se produit surtout lorsque je passe des appels et que je laisse mon application inactive pendant 10 à 15 minutes. le premier appel que je fais après retourne cette erreur.

J’ai essayé deux ou trois choses …

Je configure le gestionnaire de relance comme

 HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { public boolean retryRequest(IOException e, int retryCount, HttpContext httpCtx) { if (retryCount >= 3){ Logger.warn(CALLER, "Maximum sortinges reached, exception would be thrown to outer block"); return false; } if (e instanceof org.apache.http.NoHttpResponseException){ Logger.warn(CALLER, "No response from server on "+retryCount+" call"); return true; } return false; } }; httpPost.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler); 

mais cette tentative n’a jamais été appelée. (oui, j’utilise la clause instanceof à droite). Lors du débogage de cette classe jamais appelée.

J’ai même essayé de configurer HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false); mais pas d’utilisation. Est-ce que quelqu’un peut suggérer ce que je peux faire maintenant?

IMPORTANT En plus de comprendre pourquoi je reçois l’exception, l’une des préoccupations majeures est la suivante: pourquoi le retryhandler ne travaille-t-il pas ici?

Les connexions persistantes les plus susceptibles d’être conservées par le gestionnaire de connexions deviennent obsolètes. En d’autres termes, le serveur cible ferme la connexion à sa fin sans que HttpClient puisse réagir à cet événement, alors que la connexion est inactive, ce qui rend la connexion à moitié fermée ou «périmée». Habituellement, ce n’est pas un problème. HttpClient utilise plusieurs techniques pour vérifier la validité de la connexion lors de la location du pool. Même si la vérification de connexion périmée est désactivée et qu’une connexion périmée est utilisée pour transmettre un message de demande, l’exécution de la demande échoue généralement dans l’opération d’écriture avec SocketException et est automatiquement réessayée. Cependant, dans certaines circonstances, l’opération d’écriture peut se terminer sans exception et l’opération de lecture suivante renvoie -1 (fin du stream). Dans ce cas, HttpClient n’a pas d’autre choix que de supposer que la requête a abouti mais que le serveur n’a pas réussi à répondre en raison d’une erreur inattendue du côté du serveur.

Le moyen le plus simple de remédier à la situation est d’expulser les connexions et connexions périmées qui sont restées inactives plus longtemps, par exemple, à 1 minute de la piscine après une période d’inactivité. Pour plus de détails, consultez cette section du didacticiel HttpClient .

La réponse acceptée est correcte mais manque de solution. Pour éviter cette erreur, vous pouvez append setHttpRequestRetryHandler (ou setRetryHandler pour les composants apache 4.4) à votre client HTTP comme dans cette réponse .

HttpClient 4.4 a souffert d’un bogue dans cette zone concernant la validation des connexions éventuellement obsolètes avant de retourner au demandeur. Il n’a pas validé si une connexion était périmée, ce qui entraîne une NoHttpResponseException immédiate.

Ce problème a été résolu dans HttpClient 4.4.1. Voir cette JIRA et les notes de version

De nos jours, la plupart des connexions HTTP sont considérées comme persistantes, sauf indication contraire . Cependant, pour économiser les ressources du serveur, la connexion est rarement ouverte pour toujours, le délai de connexion par défaut pour de nombreux serveurs est plutôt court, par exemple 5 secondes pour Apache httpd 2.2 et supérieur.

L’erreur org.apache.http.NoHttpResponseException provient probablement d’une connexion persistante fermée par le serveur.

Il est possible de définir la durée maximale de conservation des connexions inutilisées dans le pool de clients HTTP Apache, en millisecondes.

Avec Spring Boot, une façon d’y parvenir:

 public class RestTemplateCustomizers { static public class MaxConnectionTimeCustomizer implements RestTemplateCustomizer { @Override public void customize(RestTemplate restTemplate) { HttpClient httpClient = HttpClientBuilder .create() .setConnectionTimeToLive(1000, TimeUnit.MILLISECONDS) .build(); restTemplate.setRequestFactory( new HttpComponentsClientHttpRequestFactory(httpClient)); } } } // In your service that uses a RestTemplate public MyRestService(RestTemplateBuilder builder ) { restTemplate = builder .customizers(new RestTemplateCustomizers.MaxConnectionTimeCustomizer()) .build(); } 

Même problème pour moi sur le client HTTP Apache 4.5.5 ajoutant un en-tête par défaut

Connexion: fermer

résoudre le problème