Dlaczego wyjątek „java.net.ConnectException: przekroczono limit czasu połączenia” miałby wystąpić, gdy adres URL jest aktywny?

86

Z ConnectException: Connection timed outpewną częstotliwością otrzymuję z mojego kodu. Adres URL, który próbuję znaleźć, jest aktywny. Ten sam kod działa dla niektórych użytkowników, ale nie dla innych. Wygląda na to, że gdy jeden użytkownik zacznie otrzymywać ten wyjątek, nadal będzie go otrzymywać.

Oto ślad stosu:

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)

Oto fragment mojego kodu:

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
źródło
7
Zaznacz jedną odpowiedź jako zaakceptowaną, jeśli rozwiązałeś swój problem :)
Tobias

Odpowiedzi:

84

Limity czasu połączenia (zakładając sieć lokalną i kilka komputerów klienckich) zwykle wynikają z

a) jakiś rodzaj firewalla na drodze, który po prostu zjada pakiety bez informowania nadawcy o takich rzeczach jak „Brak trasy do hosta”

b) utrata pakietów z powodu złej konfiguracji sieci lub przeciążenia linii

c) zbyt wiele żądań przeciążających serwer

d) mała liczba jednocześnie dostępnych wątków / procesów na serwerze, co prowadzi do ich przejęcia. Dzieje się tak zwłaszcza w przypadku żądań, których wykonanie trwa długo i może łączyć się z c).

Mam nadzieję że to pomoże.

Nerwowy
źródło
To, co pomogło mi w debugowaniu tego problemu, to wysłanie polecenia ping do serwera, do którego wysyłałem żądanie. Dowiedziałem się, że adres URL został rozstrzygnięty na publiczny adres IP, a nie prywatny adres IP, który zamierzałem. Nowe mapowanie w pliku / etc / hosts pozwoliło rozwiązać problem. Dodaję komentarz na wypadek, gdyby ktoś inny miał podobny problem.
Bouramas
31

Jeśli adres URL działa poprawnie w przeglądarce internetowej na tym samym komputerze, może to oznaczać, że kod Java nie korzysta z serwera proxy HTTP, którego przeglądarka używa do łączenia się z adresem URL.

Aleksandra
źródło
6

Komunikat o błędzie mówi wszystko: upłynął limit czasu połączenia. Oznacza to, że Twoje żądanie nie otrzymało odpowiedzi w pewnych (domyślnych) ramach czasowych. Prawdopodobnie nie otrzymano odpowiedzi:

a) Adres IP / domena lub port są nieprawidłowe

b) Adres IP / domena lub port (tj. usługa) nie działa

c) Odpowiedź IP / domeny trwa dłużej niż domyślny limit czasu

d) Masz firewall, który blokuje żądania lub odpowiedzi na dowolnym porcie, którego używasz

e) Masz firewall, który blokuje żądania do tego konkretnego hosta

f) Brak dostępu do internetu

g) Twój serwer live jest wyłączony, np. w przypadku "wywołania rest-API".

Pamiętaj, że Twój dostawca usług internetowych może mieć na swoim miejscu zapory ogniowe i blokowanie portów lub adresów IP

M Hamza Javed
źródło
4

Zalecam zwiększenie limitu czasu połączenia przed uzyskaniem strumienia wyjściowego, na przykład:

urlConnection.setConnectTimeout(1000);

Gdzie 1000 jest w milisekundach (1000 milisekund = 1 sekunda).

Władca
źródło
21
To nie podnosi jej, to drastycznie ją obniża. Domyślnie jest to około minuty i nie możesz jej zwiększyć, możesz tylko obniżyć.
Markiz Lorne,
3
  • spróbuj wykonać Telnet, aby zobaczyć problem z zaporą
  • wykonać tracert/ tracerouteznaleźć liczbę przeskoków
niebieskawy
źródło
traceroute do gdzie?
samolot
oczywiście do dowolnego adresu IP, z którym otrzymałeś błąd.
John Lord
2

Rozwiązałem swój problem z:

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

lub http.proxyHost...

NikNik
źródło
1

Może to być problem z IPv6 (host publikuje adres IPv6 AAAA, a host użytkownika uważa, że ​​jest skonfigurowany do obsługi protokołu IPv6, ale w rzeczywistości nie jest prawidłowo podłączony). Może to być również problem z MTU sieci, blokada zapory lub host docelowy może publikować różne adresy IP (losowo lub na podstawie kraju nadawcy), z których nie wszystkie są osiągalne. Lub podobne problemy z siecią.

Nie możesz zrobić wiele poza ustawieniem limitu czasu i dodaniem dobrych komunikatów o błędach (zwłaszcza wydrukowaniem rozwiązanego adresu hostów). Jeśli chcesz, aby było bardziej niezawodne, dodaj ponawianie, równoległe próbowanie wszystkich adresów, a także zajrzyj do buforowania rozpoznawania nazw (dodatnich i ujemnych) na platformie Java.

eckes
źródło
1

Dlaczego wyjątek „java.net.ConnectException: przekroczono limit czasu połączenia” miałby wystąpić, gdy adres URL jest aktywny?

Ponieważ URLConnection (HttpURLConnection / HttpsURLConnection) jest błędne. Możesz przeczytać o tym tutaj i tutaj . Nasze rozwiązanie obejmowało dwie rzeczy:

a) ustawić ContentLength za pośrednictwem setFixedLengthStreamingMode

b) złap dowolny wyjątek TimeoutException i ponów próbę, jeśli się nie powiedzie.

Lonzak
źródło
0

Istnieje możliwość, że twój adres IP / host jest blokowany przez zdalny host, zwłaszcza jeśli uważa, że ​​uderzasz go zbyt mocno.

larsivi
źródło
0

Powodem, dla którego mi się to przydarzyło, było to, że zdalny serwer zezwalał tylko na określony adres IP, ale nie na własny, i próbowałem renderować obrazy z adresów URL serwera ... więc wszystko po prostu się zatrzymywało, wyświetlając błąd przekroczenia czasu, który ty miał...

Upewnij się, że albo serwer zezwala na własny adres IP, albo renderujesz elementy z jakiegoś zdalnego adresu URL, który faktycznie istnieje.

Damir Olejar
źródło