Pourquoi une exception «java.net.ConnectException: connexion expirée» se produit-elle lorsque l'URL est active?

86

J'obtiens un ConnectException: Connection timed outavec une certaine fréquence de mon code. L'URL que j'essaie d'accéder est en place. Le même code fonctionne pour certains utilisateurs, mais pas pour d'autres. Il semble qu'une fois qu'un utilisateur commence à obtenir cette exception, il continue à l'obtenir.

Voici la trace de la pile:

java.net.ConnectException: Connection timed out
Caused by: java.net.ConnectException: Connection timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.Socket.connect(Socket.java:516)
    at java.net.Socket.connect(Socket.java:466)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:365)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:477)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:214)
    at sun.net.www.http.HttpClient.New(HttpClient.java:287)
    at sun.net.www.http.HttpClient.New(HttpClient.java:299)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:796)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:748)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:673)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:840)

Voici un extrait de mon code:

URLConnection urlConnection = null;
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;

try {
    URL url = new URL(urlBase);
    urlConnection = url.openConnection();
    urlConnection.setDoOutput(true);

    outputStream = urlConnection.getOutputStream(); // exception occurs on this line
    outputStreamWriter = new OutputStreamWriter(outputStream);
    outputStreamWriter.write(urlString);
    outputStreamWriter.flush();
    inputStream = urlConnection.getInputStream();
    String response = IOUtils.toString(inputStream);
    return processResponse(urlString, urlBase, response);
} catch (IOException e) {
    throw new Exception("Error querying url: " + urlString, e);
} finally {
    IoUtil.close(inputStream);
    IoUtil.close(outputStreamWriter);
    IoUtil.close(outputStream);
}
Sarah Haskins
la source
7
Veuillez marquer une réponse comme acceptée si vous avez résolu votre problème :)
Tobias

Réponses:

84

Les délais de connexion (en supposant un réseau local et plusieurs ordinateurs clients) résultent généralement

a) une sorte de pare-feu sur le chemin qui mange simplement les paquets sans dire à l'expéditeur des choses comme "No Route to host"

b) perte de paquets due à une mauvaise configuration du réseau ou à une surcharge de ligne

c) trop de requêtes surchargeant le serveur

d) un petit nombre de threads / processus simultanément disponibles sur le serveur, ce qui conduit à tous être pris. Cela se produit en particulier avec les requêtes qui prennent beaucoup de temps à s'exécuter et peuvent se combiner avec c).

J'espère que cela t'aides.

Nerveux
la source
Ce qui m'a aidé à déboguer ce problème était de cingler le serveur auquel je faisais la demande. J'ai découvert l'URL résolue sur l'adresse IP publique, plutôt que sur l'adresse IP privée que je voulais. Un nouveau mappage dans le fichier / etc / hosts a permis de résoudre le problème. J'ajoute le commentaire juste au cas où quelqu'un d'autre serait confronté à un problème similaire.
Bouramas
31

Si l'URL fonctionne correctement dans le navigateur Web sur la même machine, il se peut que le code Java n'utilise pas le proxy HTTP que le navigateur utilise pour se connecter à l'URL.

Alexandre
la source
6

Le message d'erreur dit tout: votre connexion a expiré. Cela signifie que votre demande n'a pas reçu de réponse dans un délai (par défaut). Les raisons pour lesquelles aucune réponse n'a été reçue sont probablement l'une des suivantes:

a) L'IP / le domaine ou le port est incorrect

b) L'IP / domaine ou port (c'est-à-dire le service) est en panne

c) L'adresse IP / le domaine prend plus de temps que votre délai par défaut pour répondre

d) Vous avez un pare-feu qui bloque les demandes ou les réponses sur le port que vous utilisez

e) Vous avez un pare-feu qui bloque les demandes adressées à cet hôte particulier

f) Votre accès Internet est en panne

g) Votre serveur live est en panne, c'est-à-dire en cas de "rest-API call".

Notez que des pare-feu et un blocage de port ou d'IP peuvent être en place par votre FAI

M Hamza Javed
la source
4

Je recommanderais d'augmenter le délai d'expiration de la connexion avant d'obtenir le flux de sortie, comme ceci:

urlConnection.setConnectTimeout(1000);

Où 1000 est en millisecondes (1000 millisecondes = 1 seconde).

Powerlord
la source
21
Cela ne l'augmente pas, c'est l'abaissement, drastiquement. Par défaut, il est d'environ une minute et vous ne pouvez pas l' augmenter, vous ne pouvez que le réduire.
Marquis of Lorne
3
  • essayez de faire le Telnet pour voir tout problème de pare-feu
  • effectuer tracert/ traceroutepour trouver le nombre de sauts
bleuâtre
la source
traceroute vers où?
avion du
évidemment, quelle que soit l'adresse IP avec laquelle vous obtenez l'erreur.
John Lord le
2

J'ai résolu mon problème avec:

System.setProperty("https.proxyHost", "myProxy");
System.setProperty("https.proxyPort", "80");

ou http.proxyHost...

NikNik
la source
1

Cela peut être un problème IPv6 (l'hôte publie une adresse IPv6 AAAA et l'hôte des utilisateurs pense qu'il est configuré pour IPv6 mais il n'est en fait pas correctement connecté). Cela peut également être un problème de réseau MTU, un blocage de pare-feu ou l'hôte cible peut publier différentes adresses IP (de manière aléatoire ou en fonction du pays d'origine) qui ne sont pas toutes accessibles. Ou des problèmes de réseau similaires.

Vous ne pouvez pas faire grand-chose à part définir un délai d'attente et ajouter de bons messages d'erreur (en particulier l'impression de l'adresse résolue des hôtes). Si vous voulez le rendre plus robuste, ajoutez une nouvelle tentative, une tentative parallèle de toutes les adresses et examinez également la mise en cache de résolution de nom (positive et négative) sur la plate-forme Java.

eckes
la source
1

Pourquoi une exception «java.net.ConnectException: connexion expirée» se produit-elle lorsque l'URL est active?

Parce que l'URLConnection (HttpURLConnection / HttpsURLConnection) est erratique. Vous pouvez en savoir plus ici et ici . Notre solution était deux choses:

a) définissez ContentLength via setFixedLengthStreamingMode

b) interceptez toute TimeoutException et réessayez si elle a échoué.

Lonzak
la source
0

Il est possible que votre IP / hôte soit bloqué par l'hôte distant, surtout s'il pense que vous le frappez trop fort.

larsivi
la source
0

La raison pour laquelle cela m'est arrivé était qu'un serveur distant n'autorisait que certaines adresses IP mais pas les siennes, et j'essayais de rendre les images à partir des URL du serveur ... donc tout s'arrêterait simplement, affichant l'erreur de temporisation eu...

Assurez-vous que le serveur autorise sa propre adresse IP ou que vous effectuez un rendu à partir d'une URL distante qui existe réellement.

Damir Olejar
la source