TCP는 전송 된 모든 패킷에 대해 새로운 연결을 엽니 다?


15

이것은 어리석은 질문 일지 모르지만 저와 소수의 친구가 TCP의 잠재적 한계를 논의하고 있습니다. 클라이언트를 수신하고 (게이트웨이를 생각할) 연결된 모든 클라이언트 데이터를 연결된 단일 kafka 게시자를 통해 하나의 주제로 라우팅하는 응용 프로그램이 있습니다.

내 친구 중 하나는 TCP가 보내는 모든 메시지 (kafka가 아니라 기본 전송 프로토콜 자체가 문제임)마다 새로운 연결을 설정하기 때문에 TCP 가이 게이트웨이에 문제가 될 것이라고 말하고 있습니다. 매번 새로운 포트가 필요합니다. 이 클라이언트 메시지 (기가 바이트)를 전송하는 속도에 따라 kafka는 읽을 포트가 부족합니다.

나는 몇 년 동안 개발을 해 왔으며 이전에 들어 본 적이 없으며 TCP 작동 방식에 대한 이해를 낮추고 싶습니다. TCP 연결을 설정할 때 응용 프로그램이 시간 초과되거나 서버 또는 클라이언트가 강제로 닫을 때까지 해당 연결이 열린 상태로 유지됩니다. 이 연결을 통해 전송되는 데이터는 스트림이며 3V (볼륨, 속도, 다양성)에 관계없이 새 연결을 열거 나 닫지 않습니다.

포트가 이동하는 한, 하나의 포트가 브로드 캐스트에 사용되고 내부 파일 디스크립터 포트는 응용 프로그램이 개별 클라이언트의 읽기 / 쓰기를 위해 관리하는 것입니다. TCP가 쓰는 모든 패킷에 대해 새로운 연결을 설정하는 것을 TCP를 이해하지 못했습니다.

이 질문이 직접적이거나 모호하지 않은 경우 사전에 사과드립니다. 나는 정말 당황스럽고 누군가 내 동료의 말에 더 많은 맥락을 제공하기를 바라고 있습니까?


13
친구가하는 말을 오해했다고 생각합니다. TCP는 그러한 작업을 수행하지 않지만 특정 클라이언트 가 전달하려는 각 메시지에 대해 새로운 TCP 연결 을 만들 수 있습니다.
hobbs

13
TCP는 새 연결을 열기 위해 여러 개의 패킷이 필요하기 때문에 각 패킷에 대해 새 연결을 열지 못했습니다. TCP에는 메시지 개념이 없으므로 각 메시지에 대해 새 연결을 열 수 없습니다. 당신의 친구는 매우 혼란 스럽다. 가장 기본적인 개념 인 TCP에 대해 이해해야 할 가장 중요한 점은 TCP가 바이트 스트림 프로토콜이라는 것입니다.
David Schwartz

1
친구의 주장이 반드시 틀린 것은 아닙니다. 응용 프로그램 수준의 연결 유지를 통해 포트를 재사용하지 않거나 단순히 너무 많은 클라이언트가있는 경우 시스템에 임시 포트가 부족할 수 있습니다. 이 문제를 해결하는 방법은 다음과 같습니다. SO_REUSEADDR소켓을 더 빨리 닫고 사용하여 임시 포트 범위를 늘리는 등의 방법이 있습니다. 또한 TCP_FASTOPEN여러 OS 수준 토글을 사용하여 잘 알려진 다른 TCP 제한 사항을 해결할 수 있습니다. 어느 쪽이든 테스트 할 워크로드가 없을 때 TCP의 한계에 대해 논의 할 필요가 없습니다.
user1643723

답변:


22

내 친구 중 하나는 TCP가 보내는 모든 메시지 (kafka가 아니라 기본 전송 프로토콜 자체가 문제임)마다 새로운 연결을 설정하기 때문에 TCP 가이 게이트웨이에 문제가 될 것이라고 말하고 있습니다. 매번 새로운 포트가 필요합니다. 이 클라이언트 메시지 (기가 바이트)를 전송하는 속도에 따라 kafka는 읽을 포트가 부족합니다.

친구가 심하게 혼란스러워합니다. TCP는 스트림 지향 프로토콜입니다. 메시지 개념이 없습니다. 물론 IP 계층에서 패킷을 사용하지만 애플리케이션에는 구현 세부 사항이 있습니다. 그렇게하는 것이 의미가 있습니다, 어디 TCP 패킷 경계를 삽입 마다 반드시 한 번하지 write()send() . 마찬가지로 read()또는에 대한 호출간에 둘 이상을 수신하면 연속 된 패킷을 결합합니다 recv().

말할 필요도없이, 모든 스트림이 새로운 연결을 설정하면이 스트림 지향 디자인은 완전히 작동하지 않을 것입니다. 따라서 새 연결을 설정하는 유일한 방법은 연결을 수동으로 닫았다가 다시 여는 것입니다.

(실제로 TCP 위에 구축 된 대부분의 프로토콜에는 HTTP 요청 및 응답과 같은 메시지와 유사한 것이 있지만 TCP는 이러한 구조를 알거나 신경 쓰지 않습니다.)

친구가 메시지를 가지고 있지만 연결이없는 UDP를 생각했을 수도 있습니다. 대부분의 소켓 구현에서는 UDP 소켓을 원격 호스트에 "연결"할 수 있지만 IP 주소와 포트를 반복해서 지정하지 않아도되는 편리한 방법입니다. 실제로 네트워킹 수준에서는 아무것도하지 않습니다. 그럼에도 불구하고 UDP에서 대화중인 피어를 수동으로 추적 할 수 있습니다. 그러나 그렇게하면 "연결"로 간주되는 것을 결정하는 것이 OS가 아니라 문제입니다. 모든 메시지에서 "연결"을 다시 설정하려면 그렇게 할 수 있습니다. 그러나 아마도 좋은 생각은 아닙니다.


9

TCP 연결을 설정할 때 응용 프로그램이 시간 초과되거나 서버 또는 클라이언트가 강제로 닫을 때까지 해당 연결이 열린 상태로 유지됩니다.

TCP의 관점에서 볼 때 클라이언트 또는 서버는 없습니다 (클라이언트 / 서버는 여기서 주제가 아닌 응용 프로그램 개념입니다). TCP는 피어 간의 연결을 설정하며 두 피어는 피어가 닫히거나 비 활동으로 인해 시간이 초과 될 때까지 연결에서 송수신 할 수 있습니다.

이 연결을 통해 전송되는 데이터는 스트림이며 3V (볼륨, 속도, 다양성)에 관계없이 새 연결을 열거 나 닫지 않습니다.

상황을 혼란스럽게 할 수있는 것은 브라우저와 같은 일부 응용 프로그램은 웹 페이지의 요소와 같은 것을 동시에로드하기 위해 여러 연결을 열 것입니다.

TCP는 전송하는 모든 세그먼트에 대해 새 연결을 열지 않지만 응용 프로그램은 여러 TCP 연결을 열 수 있습니다. 또한 TCP 연결이 닫히면 연결에 사용 된 TCP 포트가 해제되어 다시 사용할 수 있습니다. 이 답변 은 몇 가지 정보를 제공하며 TCP 용 RFC를 가리 킵니다.


2
TCP에는 연결을 시작한 파트너 ( "클라이언트"라고도 함)와 다른 파트너 ( "서버"라고 함)가 있습니다. 물론 연결이 설정되면이 차이는 더 이상 중요하지 않습니다.
Paŭlo Ebermann

2
@ PaŭloEbermann, TCP RFC에는 클라이언트 나 서버에 관한 것이 없습니다. 클라이언트 / 서버 개념은 응용 프로그램 개념입니다. 여기서 주제는 OSI 계층 -4 이하의 프로토콜이며 해당 프로토콜에는 클라이언트 나 서버가 없습니다. 실제로, 클라이언트 (TCP 연결을 여는 클라이언트)로 간주되는 것은 실제로 애플리케이션 서버 일 수 있습니다. 보안 검사 및 업데이트와 같은 작업을 수행하기 위해 클라이언트에 TCP 연결을 시작하는 서버가 있습니다.
Ron Maupin

7

아니요, TCP 는 전송되는 모든 패킷에 대해 새 연결을 열 필요 는 없습니다 .

HTTP 영구 연결을 통해 여러 패킷을 보낼 수 있습니다 .

... 모든 단일 요청 / 응답 쌍에 대해 새 연결을 여는 것과는 대조적으로 여러 HTTP 요청 / 응답을 보내고받는 단일 TCP 연결 [사용됨].

여러 연결 (연결 당 하나의 오브젝트를 전송하도록 설정된 많은 연결)과 지속적 연결 (하나의 연결이 설정되고 그 안에 전송 된 여러 오브젝트)의 차이점을 보여주는 그림이 첨부되어 있습니다.

다중 연결 및 영구 연결

출처 : https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/


7
이 답변은 혼란스러운 레이어 인 것 같습니다. HTTP 요청 / 응답은 단일 패킷이 아닙니다.
Barmar

2
말할 것도없이 모든 "open"은 실제로 3 개의 화살표 (syn, synack, ack)이며 모든 "close"는 또 다른 4 (fin, ack 2x 서버 및 클라이언트)이므로 실제로 패킷 당 연결이 있다면 오버 헤드 빨리 합쳐질 것입니다.
htmlcoderexe 16:14의

5

TCP 작동 방식에 대한 귀하의 해석은 정확합니다.

친구의 말에 관해서는 두 가지 가능성이 있습니다.

  1. 각 메시지가 새 연결을 통해 전송되는 일부 응용 프로그램 계층 제한 사항을 말하는 친구를 잘못 이해했습니다. (이것은 반드시 예외는 아닙니다. 어떤 소프트웨어에 따라이 동작을 결정할 수도 있고 그렇지 않을 수도 있습니다) 사용중인 스택);

  2. 친구가 잘못되었습니다.


5

다른 사람들이 지적한 바와 같이, TCP는 절대적으로 어느 시간 동안 어느 방향 으로든 많은 수의 "메시지"를 교환하면서 어느 정도의 연결을 유지할 수 있도록합니다. 즉, 해당 기능의 활용 여부를 결정하는 것은 궁극적으로 응용 프로그램 (클라이언트 및 서버 모두)에 달려 있습니다.

기존 TCP 연결 (소켓)을 재사용하려면 클라이언트 응용 프로그램에서 해당 소켓을 열어두고 더 많은 데이터를 작성해야 할 때 사용해야합니다. 클라이언트가이 작업을 수행하지 않고 이전 소켓을 버리고 필요할 때마다 새 소켓을 열면 실제로 새 연결을 강제 실행하여 자주 소모 될 정도로 자주 수행되는 경우 클라이언트 나 서버에서 자원 문제를 일으킬 수 있습니다 TCP 스택의 연결 풀

마찬가지로, 서버는 소켓을 옆으로 열어두고 더 많은 데이터를 기다릴만큼 충분히 똑똑해야합니다. 클라이언트와 마찬가지로 소켓을 닫을 수있는 옵션이있어 더 많은 데이터를 보내려는 내결함성 클라이언트가 새로운 소켓을 여는 것 외에 다른 문제가 발생하지 않습니다.

마지막으로, 다른 사람들이 언급했듯이 TCP는 스트림 지향적입니다. 프레이밍이 없습니다. 한 피어가 특정 방식으로 데이터를 썼기 때문에 (예 : 2,256 바이트 쓰기 호출 다음에 1,1024 바이트 쓰기 호출), 다른 피어가 동일한 크기의 청크에서 데이터를 읽을 것이라고 보장하지는 않습니다 (예 : 1536 바이트를 모두 얻을 수 있음) 한 번의 호출로). 따라서 원시 TCP 소켓을 통해 여러 개의 "메시지"를 전송하는 경우 다른 메시지를 설명하기 위해 고유 한 프레이밍 프로토콜을 제공해야합니다. 이를 수행하는 간단한 방법이 있지만,이 문제를 해결하기 위해 TCP 위에 구축 된 프로토콜이 많으므로 일반적으로 권장되지 않습니다. 자세한 내용은 https://blog.stephencleary.com/2009/04/message-framing.html을 참조하십시오.


2

친구가 TCP가 아니라 HTTP에 대해 이야기하고 있다고 생각합니다.

HTTP는 원래 상태 비 저장 프로토콜이었습니다. 각 HTTP 요청은 별도의 TCP 연결을 사용합니다. 이것이 세션을 구현하기 위해 쿠키 (또는 이와 유사한 것)가 필요한 이유입니다.


0

"단일 연결 및 매번 새 포트 필요"에 대해 언급했으며 동일한 네트워크 환경에서 PAT 기술을 사용하여 조직 외부의 서버에 연결하는 클라이언트가 많다고 해석합니다. PAT는 65535 (IPv4 주소의 TCP 세션 제한)로 제한됩니다. 사실이면 제한이 있습니다.

TCP는 전송 된 모든 패킷에 대해 새로운 연결을 엽니 다? 아니오, TCP 세션이 유효한 한 아닙니다. 그리고 ...


0

TCP 에서 훌륭한 위키 백과 페이지를 좋아합니다 . 포트 번호가 어떻게되는지 명확하게 보여줍니다. 우연히도 리소스 사용에 대한 유용한 장이 포함되어 있습니다.

자원 사용

대부분의 구현은 세션을 실행중인 운영 체제 프로세스에 매핑하는 항목을 테이블에 할당합니다. TCP 패킷에는 세션 식별자가 포함되어 있지 않으므로 두 끝점 모두 클라이언트의 주소와 포트를 사용하여 세션을 식별합니다. 패킷이 수신 될 때마다 TCP 구현은 대상 프로세스를 찾기 위해이 테이블에서 검색을 수행해야합니다. 표의 각 항목을 전송 제어 블록 또는 TCB라고합니다. 여기에는 엔드 포인트 (IP 및 포트), 연결 상태, 교환중인 패킷에 대한 데이터 실행 및 데이터 송수신을위한 버퍼에 대한 정보가 포함됩니다.

서버 측의 세션 수는 메모리에 의해서만 제한되며 새 연결이 도착하면 커질 수 있지만 클라이언트는 첫 번째 SYN을 서버로 보내기 전에 임의의 포트를 할당해야합니다. 이 포트는 전체 대화 중에 할당 된 상태로 유지되며 각 클라이언트의 IP 주소에서 나가는 연결 수를 효과적으로 제한합니다. 응용 프로그램이 필요하지 않은 연결을 제대로 닫지 못하면 클라이언트에 리소스가 부족하여 다른 응용 프로그램에서도 새 TCP 연결을 설정할 수 없습니다.

간단히 말해서, TCP는 클라이언트의 포트 수인 매우 유한 한 하나의 자원을 사용합니다 (TCP 헤더의 포트 필드 크기, 16 비트로 제한됨).

그래서, TCP는 것입니다 클라이언트를 종료하지 않고 병렬로 TCP 연결을 많이 여는 경우, 포트 밖으로 실행할 수. 이 문제 는 클라이언트 측 에서만 발생하며 연결이 동일하거나 다른 서버 IP 주소 또는 서버 포트를 사용하는지 여부는 중요하지 않습니다.

귀하의 설정에서, 당신은 많은 클라이언트 요청에 소요 한 응용 프로그램을 (갖고있는 것 같다 이러한클라이언트 가이 이벤트를 사용하여 응용 프로그램에 일부 이벤트를 기록하고 TCP 채널을 열어 두지 않는 경우와 같이 개별 TCP 요청이 될 수 있으며 Kafka 브로커에 새로운 내부 요청을 생성합니다 (이는 개별 TCP 연결 일 수 있음) 이런 식으로 구현하기로 선택한 경우). 이 경우 병목 현상 (성능이 아닌 리소스 측면에서)은 클라이언트로부터 동시에 많은 수의 요청을 처리 할 경우에 발생합니다 (서버 측에서는 포트가 하나만 필요하므로 문제 없습니다). Kafka에 대한 많은 수의 전달 요청을 열면 Kafka는 신속하게 처리 할 수 ​​없으므로 16 비트 이상의 연결을 동시에 열 수 있습니다.

당신은 여기에 자신의 판사입니다; 애플리케이션을 확인하고 매번 별도의 요청으로 Kafka에 연결하고 있는지 확인하십시오 (일부 REST API 프록시를 통해). 그렇게하고 수많은 고객이 있다면 위험에 처하게됩니다.

65k 미만의 소수의 클라이언트 만 있고 /하거나 Kafka 브라우저에 단일 연결을 유지하면 괜찮을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.