Почему возникает исключение "java.net.ConnectException: истекло время ожидания соединения", когда URL-адрес активен?

Я получаю ConnectException: Connection timed out с некоторой частотой из моего кода. URL, на который я пытаюсь попасть, работает. Тот же код работает для некоторых пользователей, но не для других. Кажется, что как только один пользователь начинает получать это исключение, он продолжает получать исключение.

Вот трассировка стека:

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)

Вот фрагмент из моего кода:

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

11 ответов

Тайм-ауты соединения (при условии, что локальная сеть и несколько клиентских машин) обычно

а) какой-то брандмауэр на пути, который просто ест пакеты, не сообщая отправителю такие вещи, как "Нет маршрута к хосту"

б) потеря пакета из-за неправильной конфигурации сети или перегрузки линии

в) слишком много запросов, перегружающих сервер

d) небольшое количество одновременно доступных потоков / процессов на сервере, что приводит к тому, что все они принимаются. Это особенно актуально для запросов, выполнение которых занимает много времени и может сочетаться с c).

Надеюсь это поможет.

Если URL-адрес работает в веб-браузере на том же компьютере, возможно, код Java не использует прокси-сервер HTTP, который браузер использует для подключения к URL-адресу.

Сообщение об ошибке говорит само за себя: ваше соединение истекло. Это означает, что ваш запрос не получил ответа в течение некоторого (по умолчанию) срока. Причинами того, что ответ не был получен, может быть одна из:

а) IP/ домен или порт неверны

б) IP/ домен или порт (то есть сервис) не работает

c) IP/ домен занимает больше времени, чем ваш тайм-аут по умолчанию, чтобы ответить

г) у вас есть брандмауэр, который блокирует запросы или ответы на порт, который вы используете

e) у вас есть брандмауэр, который блокирует запросы к этому конкретному хосту

е) Ваш доступ в интернет недоступен

g) Ваш live-сервер не работает, т.е. в случае "вызова rest-API".

Обратите внимание, что ваш интернет-провайдер может использовать брандмауэры и блокировку портов или IP-адресов.

Я бы рекомендовал увеличить время ожидания соединения до получения выходного потока, например так:

urlConnection.setConnectTimeout(1000);

Где 1000 в миллисекундах (1000 миллисекунд = 1 секунда).

  • попробуйте сделать Telnet, чтобы увидеть любые проблемы с брандмауэром
  • выполнять tracert/traceroute найти количество прыжков

Я решил свою проблему с:

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

или же http.proxyHost...

Почему возникает исключение "java.net.ConnectException: время ожидания соединения истекло", когда URL открыт?

Поскольку URLConnection (HttpURLConnection/HttpsURLConnection) ошибочен. Вы можете прочитать об этом здесь и здесь. Нашим решением были две вещи:

а) установите ContentLength через setFixedLengthStreamingMode

б) поймать любое исключение TimeoutException и повторить попытку, если это не удалось.

Это может быть проблемой IPv6 (хост публикует AAvA-адрес IPv6, а хост пользователей считает, что он настроен для IPv6, но на самом деле он подключен неправильно). Это также может быть проблема сетевого MTU, блока брандмауэра или целевой хост может публиковать разные IP-адреса (случайным образом или в зависимости от страны отправителя), которые не все доступны. Или схожие проблемы с сетью.

Вы не можете сделать ничего, кроме установки тайм-аута и добавления хороших сообщений об ошибках (особенно распечатывания разрешенного адреса хостов). Если вы хотите сделать его более надежным, добавьте повтор, параллельные попытки всех адресов, а также изучите кэширование разрешения имен (положительное и отрицательное) на платформе Java.

Существует вероятность того, что ваш IP/ хост заблокирован удаленным хостом, особенно если он считает, что вы слишком сильно его ударили.

Причина, по которой это произошло со мной, заключалась в том, что удаленный сервер разрешал только определенный IP-адрес, но не свой собственный, и я пытался отобразить изображения с URL-адресов сервера... так что все просто остановилось бы, отображая ошибку времени ожидания, которую вы имел...

Убедитесь, что либо сервер разрешает свой собственный IP, либо вы выводите вещи с какого-то удаленного URL, который действительно существует.

Моя VPN была отключена и вызвала эту проблему. Повторно подключил VPN, и он начал работать.

Другие вопросы по тегам