바인딩 실패, 주소 사용 중: 원본과 대상 모두에 TCP 포트를 사용할 수 없나요?

바인딩 실패, 주소 사용 중: 원본과 대상 모두에 TCP 포트를 사용할 수 없나요?

시작되지 않는 Hadoop DataNode를 디버깅하고 있습니다. 우리는 머신에서 saltstack과 elasticsearch를 사용합니다.

Hadoop DataNode 오류는 매우 분명합니다.

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포트 50020의 경우 이미 사용 중이지만 대상 포트가 아닌 소스 포트로만 사용됩니다.

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)

그러나 0.0.0.0의 바인딩은 작동하지 않는 것 같습니다.

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

의도적인 걸까요? 해당 포트가 이미 소스 포트로 사용되고 있는 경우에는 0.0.0.0으로 바인딩이 허용되지 않나요? 소켓에서 아무것도 수신하지 않습니다. 왜 작동하지 않아야 하는지 모르겠습니다.

우분투 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

답변1

50020이 소스 포트인지 대상 포트인지는 중요하지 않습니다. 선언되면 선언된 것입니다.

IANA에서 정의한 임시 포트이므로 49152 - 65535 범위의 특정 포트에서 서비스를 시작해야 하는 것은 버그라고 생각합니다. 많은 Linux 배포판에서는 32768 이상의 포트를 임시 포트로 취급합니다. 다음 명령을 사용하여 현재 임시 포트 범위를 볼 수 있습니다.

cat /proc/sys/net/ipv4/ip_local_port_range

모든 애플리케이션은 임시 포트 범위만 사용할 수 있으므로 특정 포트가 항상 무료라는 보장은 없습니다. 1024~32767 사이에서 사용하지 않는 포트를 선택하는 것이 가장 좋습니다.

소개 보기임시 포트.

Hadoop DataNode 요구 사항을 충족하기 위해 임시 범위를 변경하려면 /etc/sysctl.conf다음과 같이 줄을 편집하고 설정하면 됩니다.

net.ipv4.ip_local_port_range=56000 65000

편집하다:충분히 새로운 커널(변경 사항은 2010년 5월에 커밋됨)을 사용하면 이 범위에 예외가 적용될 수 있음을 간접적으로 지적한 @mr.spuratic에게 감사드립니다. 범위를 가지고 노는 것은 그 자체로 상당한 변화이므로 이는 권장됩니다.

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

에서 인용문서/네트워크/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

답변2

나는 이것이 정상적인 동작이라고 생각합니다. 포트가 사용되면 사용됩니다. 소스나 대상은 중요하지 않습니다.

0.0.0.0은 해당 포트에서 수신하려는 모든 네트워크 주소를 의미합니다. 따라서 IP 주소가 2개(예: 192.168.1.20 및 10.4.2.1)인 경우 IP 주소를 지정하면 포트를 두 번 사용할 수 있습니다.

답변3

그러나 0.0.0.0의 바인딩은 작동하지 않는 것 같습니다.

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

의도적인 걸까요? 해당 포트가 이미 소스 포트로 사용되고 있는 경우에는 0.0.0.0으로 바인딩이 허용되지 않나요? 소켓에서 아무것도 수신하지 않습니다. 왜 작동하지 않아야 하는지 모르겠습니다.

이것은 완전히 정상입니다. 특수 IP 주소 0.0.0.0은 시스템이 "모든" 인터넷 프로토콜 주소에 응답한다는 것을 의미하며, 이는 시스템의 모든 IP 주소에 바인딩된다는 의미입니다. 모든 TCP 연결은 양방향 상태 저장 연결이며 원본/대상은 실제로 초기 핸드셰이크 중에만 의미가 있습니다. 실제로 중요한 것은 연결 끝의 포트 번호입니다.

IP 스택 측면에서 문제를 생각해 보십시오. xx.xx.132.72:50020에 기존 TCP 연결이 있고 청취 소켓을 0.0.0.0:50020에 바인딩하려고 합니다. 이 특정 주소는 xx.xx.132.72:50020을 포함하도록 확장되었지만 사용 시 실패했습니다. 실패하지 않으면 해당 주소로 인바운드되는 IP 패킷이 청취 소켓으로 전달되고 있는지 아니면 기존 연결로 전달되고 있는지 어떻게 식별합니까? 물론 여러 소켓이 하나의 포트를 공유하도록 허용하는 시나리오를 구상할 수 있지만 애초에 포트가 해결하려고 했던 문제를 이미 다시 설계했습니다.

청취 소켓은 신뢰할 수 있는 위치에서 액세스해야 하므로 포트 번호를 더 잘 선언할 수 있으므로 다른 애플리케이션 포트를 변경해야 합니다. 구성할 수 없는 경우 다른 응용 프로그램을 중지하고 서버를 시작한 다음 응용 프로그램을 다시 시작하면 응용 프로그램이 나가는 연결에 사용 가능한 다른 소스 포트를 사용하고 더 이상 서버와 충돌하지 않습니다.

관련 정보