Perché si verifica un'eccezione "java.net.ConnectException: connessione scaduta" quando l'URL è attivo?


86

Ricevo un messaggio ConnectException: Connection timed outcon una certa frequenza dal mio codice. L'URL che sto cercando di raggiungere è attivo. Lo stesso codice funziona per alcuni utenti, ma non per altri. Sembra che quando un utente inizia a ricevere questa eccezione, continua a ricevere l'eccezione.

Ecco la traccia dello stack:

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)

Ecco uno snippet del mio codice:

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);
}

7
Contrassegna una risposta come accettata se hai risolto il problema :)
Tobias

Risposte:


84

I timeout di connessione (presupponendo una rete locale e diverse macchine client) derivano in genere da

a) una sorta di firewall sulla strada che semplicemente mangia i pacchetti senza dire al mittente cose come "Nessun percorso verso l'host"

b) perdita di pacchetti dovuta a configurazione di rete errata o sovraccarico di linea

c) troppe richieste sovraccaricano il server

d) un piccolo numero di thread / processi disponibili simultaneamente sul server che porta a tutti loro presi. Ciò accade soprattutto con richieste che richiedono molto tempo per essere eseguite e possono combinarsi con c).

Spero che sia di aiuto.


Ciò che mi ha aiutato a eseguire il debug di questo problema è stato eseguire il ping del server a cui stavo effettuando la richiesta. Ho scoperto che l'URL è stato risolto sull'IP pubblico, piuttosto che sull'IP privato che intendevo. Una nuova mappatura nel file / etc / hosts ha permesso di risolvere il problema. Aggiungo il commento nel caso in cui qualcun altro affronti un problema simile.
Bouramas

31

Se l'URL funziona correttamente nel browser Web sulla stessa macchina, è possibile che il codice Java non utilizzi il proxy HTTP utilizzato dal browser per connettersi all'URL.


6

Il messaggio di errore dice tutto: la connessione è scaduta. Ciò significa che la tua richiesta non ha ricevuto risposta entro un periodo di tempo (predefinito). È probabile che i motivi per cui non è stata ricevuta alcuna risposta siano:

a) L'IP / dominio o la porta non sono corretti

b) L'IP / dominio o la porta (cioè il servizio) è inattivo

c) L'IP / dominio impiega più tempo del timeout predefinito per rispondere

d) Hai un firewall che blocca le richieste o le risposte su qualunque porta tu stia utilizzando

e) Hai un firewall che blocca le richieste a quel particolare host

f) Il tuo accesso a Internet è inattivo

g) Il tuo server live è inattivo, ad esempio in caso di "chiamata API rest".

Tieni presente che i firewall e il blocco della porta o dell'IP potrebbero essere stati attivati ​​dal tuo ISP


4

Consiglierei di aumentare il tempo di timeout della connessione prima di ottenere il flusso di output, in questo modo:

urlConnection.setConnectTimeout(1000);

Dove 1000 è in millisecondi (1000 millisecondi = 1 secondo).


21
Questo non è alzarlo, è abbassarlo, drasticamente. Per impostazione predefinita è circa un minuto e non puoi aumentarlo, puoi solo abbassarlo.
Marchese di Lorne

3
  • prova a fare il Telnet per vedere qualsiasi problema del firewall
  • eseguire tracert/ tracerouteper trovare il numero di salti

traceroute a dove?
aereo il

ovviamente, a qualunque ip con cui stavi ricevendo l'errore.
John Lord il

2

Ho risolto il mio problema con:

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

oppure http.proxyHost...


1

Questo può essere un problema IPv6 (l'host pubblica un indirizzo IPv6 AAAA e l'host dell'utente pensa che sia configurato per IPv6 ma in realtà non è connesso correttamente). Questo può anche essere un problema MTU di rete, un blocco del firewall o l'host di destinazione potrebbe pubblicare diversi indirizzi IP (in modo casuale o in base al paese di origine) che non sono tutti raggiungibili. O problemi di rete simili.

Non puoi fare molto oltre a impostare un timeout e aggiungere buoni messaggi di errore (in particolare stampare l'indirizzo risolto degli host). Se vuoi renderlo più robusto, aggiungi un nuovo tentativo, un tentativo parallelo di tutti gli indirizzi e controlla anche la memorizzazione nella cache della risoluzione dei nomi (positiva e negativa) sulla piattaforma Java.


1

Perché si verifica un'eccezione "java.net.ConnectException: connessione scaduta" quando l'URL è attivo?

Perché URLConnection (HttpURLConnection / HttpsURLConnection) è irregolare. Puoi leggere su questo qui e qui . La nostra soluzione era due cose:

a) impostare ContentLength tramite setFixedLengthStreamingMode

b) intercettare qualsiasi TimeoutException e riprovare se fallisce.


0

Esiste la possibilità che il tuo IP / host sia bloccato dall'host remoto, soprattutto se pensa che tu lo stia colpendo troppo forte.


0

Il motivo per cui questo mi è successo era che un server remoto consentiva solo determinati indirizzi IP ma non il proprio, e stavo cercando di eseguire il rendering delle immagini dagli URL del server ... quindi tutto si sarebbe semplicemente fermato, visualizzando l'errore di timeout che tu aveva...

Assicurati che il server stia consentendo il proprio IP o che stai eseguendo il rendering delle cose da un URL remoto che esiste effettivamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.