falha de ligação, endereço em uso: Não é possível usar uma porta TCP para origem e destino?

3

Estou depurando o DataNodes do Hadoop que não é iniciado. Estamos usando o palheiro e também elasticsearch nas máquinas.

O erro Hadoop DataNode é bem claro:

java.net.BindException: Problem binding to [0.0.0.0:50020]    
java.net.BindException: Address already in use; 
      For more details see:  http://wiki.apache.org/hadoop/BindException

[...]

Caused by: java.net.BindException: Address already in use

[...]

(ExitUtil.java:terminate(124)) - Exiting with status 1

lsof -i -n para a porta 50020 diz que já está sendo usado, mas apenas como porta de origem e não porta de destino:

salt-mini 1733          root   25u  IPv4  17452      0t0  TCP xx.xx.132.72:50020->xx.xx.132.20:4505 (ESTABLISHED)
java      2789 elasticsearch 2127u  IPv6   9808      0t0  TCP xx.xx.132.72:50020->xx.xx.132.55:9300 (ESTABLISHED)

No entanto, a ligação em 0.0.0.0 parece não funcionar:

root@host:~# nc -l 50020
nc: Address already in use

Isso é intencional? A ligação a 0.0.0.0 não é permitida quando a porta já está sendo usada uma porta de origem? Não há nada escutando o soquete - eu realmente não sei porque não deveria funcionar.

Ubuntu 14.04:

root@host:~# uname -a
Linux host 4.2.0-19-generic #23~14.04.1-Ubuntu SMP Thu Nov 12 12:33:30 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
    
por mt_ 14.12.2015 / 14:00

3 respostas

11

Não importa se 50020 é uma porta de origem ou destino: se for reivindicado, é reivindicado.

Eu consideraria um bug precisar iniciar um serviço em uma porta específica no intervalo 49152 - 65535, pois essas são as portas efêmeras definidas pela IANA. Muitas distribuições do Linux consideram as portas superiores a 32768 como efêmeras. Você pode revisar o intervalo de portas efêmeras no momento com:

cat /proc/sys/net/ipv4/ip_local_port_range

Qualquer aplicativo pode usar apenas uma porta do intervalo efêmero, portanto, não há garantia de que uma porta específica sempre estará livre. Melhor escolher uma porta não usada entre 1024 e 32767.

Veja alguma introdução em portas efêmeras .

Se você quiser alterar o intervalo efêmero para atender ao requisito do DataNode do Hadoop, poderá fazê-lo editando /etc/sysctl.conf e definindo uma linha ao longo do seguinte:

net.ipv4.ip_local_port_range=56000 65000

edit: Obrigado @ mr.spuratic, que apontou indiretamente que com um kernel recente o suficiente (a mudança foi confirmada em maio de 2010), é possível fazer exceções ao intervalo. Isto é recomendado, pois brincar com o intervalo em si é uma mudança drástica.

sysctl -w net.ipv4.ip_local_reserved_ports = 50020, 50021

Citações de Documentação / rede / ip-sysctl.txt

ip_local_reserved_ports - list of comma separated ranges

Specify the ports which are reserved for known third-party
applications. These ports will not be used by automatic port
assignments (e.g. when calling connect() or bind() with port
number 0). Explicit port allocation behavior is unchanged.

The format used for both input and output is a comma separated
list of ranges (e.g. "1,2-4,10-10" for ports 1, 2, 3, 4 and
10). Writing to the file will clear all previously reserved
ports and update the current list with the one given in the
input.

Note that ip_local_port_range and ip_local_reserved_ports
settings are independent and both are considered by the kernel
when determining which ports are available for automatic port
assignments.

You can reserve ports which are not in the current
ip_local_port_range, e.g.:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32000   60999
$ cat /proc/sys/net/ipv4/ip_local_reserved_ports
8080,9148

although this is redundant. However such a setting is useful
if later the port range is changed to a value that will
include the reserved ports.

Default: Empty
    
por 14.12.2015 / 14:50
1

Eu acho que é um comportamento normal Se uma porta é usada, é usada. Fonte ou Destino não importa.

0.0.0.0 significa que você está tentando escutar todos os endereços de rede para essa porta. Então, se você tem dois endereços IP, digamos 192.168.1.20 & 10.4.2.1 você pode usar a porta duas vezes se você especificar o endereço IP

    
por 14.12.2015 / 14:51
1

However binding on 0.0.0.0 does not seem to work:

root@host:~# nc -l 50020
nc: Address already in use

Is this intentional? Is binding to 0.0.0.0 disallowed when the port is already used a source port? There is nothing listening to the socket - I don't really know why it shouldn't work.

Isso é totalmente normal. O endereço IP especial 0.0.0.0 significa "qualquer" endereço de protocolo de internet a que esta máquina responde, o que significa que se liga a todos os endereços IP no sistema. Cada conexão TCP é uma conexão stateful de duas vias e a origem / destino realmente só tem significado a partir do handshake inicial. Tudo o que realmente importa para você é o número da porta do seu lado da conexão.

Considere o que você está perguntando do ponto de vista da pilha de IPs. Ele tem uma conexão TCP existente em xx.xx.132.72: 50020 e você está tentando ligar um soquete de escuta a 0.0.0.0:50020. Este endereço especial se expande para incluir xx.xx.132.72: 50020 e falha como em uso. Se não falhasse, como um pacote IP de entrada para esse endereço poderia discernir se ele deveria ser entregue ao seu soquete de escuta ou à conexão preexistente? Claro que você poderia visualizar um esquema para permitir que vários soquetes compartilhem uma porta, mas então você terá reprojetado exatamente o problema que as portas resolvem em primeiro lugar.

Seu soquete de escuta provavelmente possui melhores declarações para um número de porta, já que ele precisa ser acessado em um local confiável, portanto, é necessário alterar a porta de outros aplicativos. Se não for configurável, basta parar o outro aplicativo, iniciar seu servidor e, em seguida, reiniciar o aplicativo, que usará uma porta de origem diferente e disponível para sua conexão de saída e não entrará mais em conflito com seu servidor.

    
por 14.12.2015 / 18:22

Tags