Por que uma exceção “java.net.ConnectException: Connection timed out” ocorreria quando o URL estivesse ativo?

86

Estou recebendo um ConnectException: Connection timed outcom alguma frequência do meu código. O URL que estou tentando acessar está ativo. O mesmo código funciona para alguns usuários, mas não para outros. Parece que quando um usuário começa a obter essa exceção, ele continua a obter a exceção.

Aqui está o rastreamento de pilha:

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)

Aqui está um snippet do meu código:

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
fonte
7
Por favor, marque uma resposta como aceita se você tiver resolvido seu problema :)
Tobias

Respostas:

84

Os tempos limite de conexão (assumindo uma rede local e várias máquinas clientes) normalmente resultam de

a) algum tipo de firewall no caminho que simplesmente devora os pacotes sem dizer ao remetente coisas como "Sem rota para o host"

b) perda de pacotes devido à configuração de rede incorreta ou sobrecarga de linha

c) muitas solicitações sobrecarregando o servidor

d) um pequeno número de threads / processos disponíveis simultaneamente no servidor, o que faz com que todos sejam capturados. Isso acontece especialmente com solicitações que demoram muito para serem executadas e podem ser combinadas com c).

Espero que isto ajude.

Jumpy
fonte
O que me ajudou a depurar esse problema foi executar ping no servidor para o qual eu estava fazendo a solicitação. Eu descobri que a URL resolvia para o IP público, ao invés do IP privado que eu pretendia. Um novo mapeamento no arquivo / etc / hosts permitiu corrigir o problema. Estou adicionando o comentário para o caso de outra pessoa enfrentar um problema semelhante.
Bouramas
31

Se o URL funcionar bem no navegador da web da mesma máquina, pode ser que o código Java não esteja usando o proxy HTTP que o navegador está usando para se conectar ao URL.

Alexandre
fonte
6

A mensagem de erro diz tudo: sua conexão expirou. Isso significa que sua solicitação não obteve resposta dentro de algum prazo (padrão). Os motivos pelos quais nenhuma resposta foi recebida provavelmente serão:

a) O IP / domínio ou porta está incorreto

b) O IP / domínio ou porta (ou seja, serviço) está inativo

c) O IP / domínio está demorando mais do que o tempo limite padrão para responder

d) Você tem um firewall que está bloqueando solicitações ou respostas em qualquer porta que estiver usando

e) Você tem um firewall que está bloqueando solicitações para esse host específico

f) Seu acesso à internet está baixo

g) Seu servidor ativo está inativo, ou seja, em caso de "chamada de API rest".

Observe que firewalls e porta ou bloqueio de IP podem estar em vigor pelo seu ISP

M Hamza Javed
fonte
4

Eu recomendo aumentar o tempo limite de conexão antes de obter o fluxo de saída, assim:

urlConnection.setConnectTimeout(1000);

Onde 1000 está em milissegundos (1000 milissegundos = 1 segundo).

Powerlord
fonte
21
Isso não é aumentá-lo, isso é diminuí-lo drasticamente. Por padrão, é cerca de um minuto e você não pode aumentá-lo, você pode apenas diminuí-lo.
Marquês de Lorne
3
  • tente fazer o Telnet para ver qualquer problema de firewall
  • realizar tracert/ tracerouteencontrar o número de saltos
azulado
fonte
traceroute para onde?
aeronave
obviamente, para qualquer ip com o qual você estava recebendo o erro.
John Lord
2

Resolvi meu problema com:

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

ou http.proxyHost...

NikNik
fonte
1

Isso pode ser um problema de IPv6 (o host publica um endereço AAAA IPv6 e o ​​host do usuário pensa que está configurado para IPv6, mas na verdade não está conectado corretamente). Isso também pode ser um problema de MTU de rede, um bloqueio de firewall ou o host de destino pode publicar endereços IP diferentes (aleatoriamente ou com base no país de origem) que nem todos são acessíveis. Ou problemas de rede semelhantes.

Você não pode fazer muito além de definir um tempo limite e adicionar boas mensagens de erro (especialmente imprimir o endereço resolvido dos hosts). Se você quiser torná-lo mais robusto, adicione nova tentativa, tentativa paralela de todos os endereços e também observe o cache de resolução de nomes (positivo e negativo) na plataforma Java.

eckes
fonte
1

Por que uma exceção “java.net.ConnectException: Connection timed out” ocorreria quando o URL estivesse ativo?

Porque o URLConnection (HttpURLConnection / HttpsURLConnection) é errático. Você pode ler sobre isso aqui e aqui . Nossa solução foram duas coisas:

a) definir o ContentLength via setFixedLengthStreamingMode

b) capturar qualquer TimeoutException e tentar novamente se ela falhar.

Lonzak
fonte
0

Existe a possibilidade de que o seu IP / host seja bloqueado pelo host remoto, especialmente se ele achar que você está batendo com força.

Larsivi
fonte
0

O motivo pelo qual isso aconteceu comigo foi que um servidor remoto estava permitindo apenas determinados endereços IP, mas não o seu próprio, e eu estava tentando renderizar as imagens dos URLs do servidor ... então tudo simplesmente parava, exibindo o erro de tempo limite que você teve...

Certifique-se de que o servidor está permitindo seu próprio IP ou que você está renderizando coisas de algum URL remoto que realmente existe.

Damir Olejar
fonte