https://sundaland.tistory.com/13
[ ▶ TCP 프로토콜 ]
[ ▷Connection Establishment ]
TCP (Transmission Control Protocol)의 연결 설정 (Connection Establishemnt) 과정에서 3-way 핸드쉐이크를 사용한다. 그러나, 3-way 핸드쉐이크는 연결을 시작할 때만 사용된다. 즉 데이터 통신을 시작하기 전에만 수행된다. 연결이 성립된 후의 데이터 전송 과정에서는 3-way 핸드쉐이크 과정을 다시 거치치 않는다.
- SYN: 클라이언트를 서버에게 SYN 패킷을 연결을 요청한다.
- SYN-ACK: 서버는 클라이언트의 요청을 받고, SYN-ACK 패킷을 보내 연결을 수작한다.
- ACK: 클라이언트는 서버에게 ACK 패킷을 보내 연결을 확정한다.
이렇게 3-way 핸드쉐이크를 통해 연결이 성립되면, TCP는 신뢰성 있는 데이터 전송을 보장하기 위해 패킷 손실, 순서, 오류 등을 관리하면서 데이터를 전송한다. 하지만, 각각의 데이터 패킷 전송시 마다 3-way 핸드쉐이크를 하는 것은 아니다.
연결 종료시에는 4-way 핸드쉐이크라는 다른 과정을 사용한다.
[ ▷ Data Transfer ]
연결이 성립된 후 TCP 데이터 통신은 2-way 핸드쉐이크와 유사한 방식으로 이루어지지만, 이를 일반적은 2-way 핸드쉐이크라고 부르지는 않는다. 이 과정은 TCP의 신뢰성 있는 데이터 전송을 위한 Acknowledgment 과정으로 더 정확하게 설명된다.
TCP 데이터 통신 과정에서는 아래와 같은 방식으로 데이터 전송이 이루어진다.
- 데이터 전송: 송신측은 수신측에게 데이터 패킷을 보낸다.
- ACK 응답: 수신측은 데이터 패킷을 받고, 그것을 확인한 후 ACK 패킷을 송신 측에게 보내 데이터를 잘 받았다고 알린다.
이 과정에서 중요한 점은 TCP가 신뢰성 있는 데이터 전송을 제공한다는 것이다. 이는 수신측이 송신측에게 데이터를 제대로 받았다는 신호 (ACK)를 보내줌으로써, 송신측이 데이터가 정상적으로 전송되었는지 확인할 수 있게 해준다. 패킷이 손실되거나 오류가 발생한 경우, TCP는 재전송 메커니즘을 사용하여 데이터의 정확한 전송을 보장한다.
따라사, 각각의 데이터 전송마다 ACK 메시지를 통해 데이터 전송의 성공 여부를 확인하는 과정이다.
[ ▷ Sequence Number ]
TCP (Transmission Control Protocol)에서 시퀀스 넘버 (Sequence Number)는 매우 중요한 역할을 한다. 시퀀스 넘버는 각 TCP 세그먼트에 할당되어, 데이터가 네트워크를 통해 전송되는 동안 이 데이터터가 어떤 순서로 송수신 되어야 하는지를 결정하는데 사용된다. 이 시스템은 TCP가 신뢰성 있는 데이터 전송을 제공하는데 핵심적인 역할을 한다.
- 데이터 순서 보장: 시퀀스 넘버는 네트워크를 통해 전송된 데이터의 순서를 유지하는데 사용된다. 이를 통해 수신측은 올바른 순서로 데이터를 재조립할 수 있다.
- 데이터 무결성: 만약 패킷 중 일부가 손실되거나 순서가 바뀌면, 시퀀스 넘버를 통해 이를 감지하고 재전송을 요청할 수 있다.
- 중복 데이터 제거: 수신측은 이미 수신한 시퀀스 넘버의 데이터를 다시 받을 경우 이를 중복으로 인식하고 무시할 수 있다.
- 흐름 제어 및 혼잡 제어: 시퀀스 넘버를 사용하여 네트워크의 혼잡 상황을 모니터링하고, 데이터 전송 속도를 조절할 수 있다.
- 초기 시퀀스 넘버 (ISN): TCP 연결이 시작될 때, 각 연결의 시작점에 대한 초기 시퀀스 넘버가 임의로 설정된다. 이 넘버는 연결 설정 (3-way 핸드쉐이크) 과정에서 중요한 역할을 한다.
- 순차적 증가: 데이터가 전송될 때마다, 시퀀스 넘버는 전송된 바이트 수만큼 증가한다. 예를 들어, 시퀀스 넘버가 1이고 10바이트의 데이터가 전송된 경우, 다음 시퀀스 넘버는 11이 된다.
- ACK와의 관계: 수신측은 전송된 데이터를 확인한 후, 다음에 기대하는 시퀀스 넘버를 포함한 ACK 패킷을 보낸다. 이를 송친측은 어느 부분까지 데이터가 성공적으로 전송되었는지 알 수 있다.
TCP의 시퀀스 넘버는 프로토콜의 신뢰성과 효율성을 높이는데 필수적인 요소로, 네트워크 통신에서 데이터의 정확하고 효율적인 전송을 보장하는데 중요한 역할을 한다.
[ ▷ Acknowledgment Number ]
TCP의 ACK 패킷에는 시퀀스 넘버와 관련된 중요한 정보인 ACK 넘버가 포함되어 있다. 이 번호는 TCP의 신뢰성 있는 통신을 위해 필수적인 역할을 한다.
- 다음 기대 시퀀스 넘버: ACK 패킷의 ACK 넘버는 수신측이 다음에 기대하는 시퀀스 넘버를 나타낸다. 이는 수신측이 현재까지 성공적으로 받은 데이터의 시퀀스 넘버의 끝을 나타내며, 다음에 예상되는 데이터의 시작 시퀀스 넘버이다.
- 데이터 수신 확인: 송신측은 이 ACK 넘버를 통해 자신이 보낸 데이터가 수신측에 의해 성공적으로 받아졌음을 확인할 수 있다. 만약 예상한 ACK 넘버를 받지 못한다면, 데이터가 제대로 전송되지 않았을 가능성이 있으며, 이 경우 재전송이 이루어질 수 있다.
예를 들어, 송신측이 시퀀스 넘버 1부터 시작하여 100바이트의 데이터를 전송했다고 가정한다. 이 데이터가 성공적으로 수신되었다면, 수신측은 ACK 패킷을 보내고, 이 패킷의 ACK 넘버는 101이된다. 이는 수신측이 다음에 기대하는 데이터의 시퀀스 넘버가 101임을 의미한다.
이 ACK 넘버는 메커니즘을 탱해 TCP는 데이터의 순서를 유지하고, 신뢰성 있는 데이터 전송을 보장한다. 손실이나 오류가 발생한 경우, 송신측은 누락된 데이터가 오류가 발생한 데이터를 다시 전송할 수 있다.
[ ▷ Connection Termination ]
TCP 연결을 종료할 때 사용되는 4-way 핸드쉐이크는 연결 설정 과정에서의 3-way 핸드쉐이크와는 다르다. 4-way 핸드쉐이크는 연결을 종료하기 위해 양쪽 통신 당사자가 각각 연결 종료를 시작하고 확인하는 과정으로 구성된다. 이 과정은 TCP가 전이중 (Full-duplex) 통신을 사용하며, 각 방향의 통신을 개별적으로 종료할 수 있어야 하기 때문에 필요하다.
△ 4-way 핸드쉐이크 과정
- FIN (Finish) 전송: 연결을 종료하고자 하는 측 (일반적으로 클라이언트)은 FIN 플래그가 설정된 세그먼트를 전송하여 연결 종료를 시작한다. 이는 더 이상 전송할 데이터가 없다는 것을 나타낸다.
- ACK 응답: 수신측 (서버)은 FIN 세그먼트를 받고, 이에 대한 ACK를 송신측에 보내 연결 종료 요청을 받았음을 확인한다. 이 시점에서, 송신측의 연결은 종료 상태로 이동하지만, 수신측은 아직 자신의 데이터를 전송할 수 있다.
- FIN 전송 (수신측에서): 수신측이 모둔 데이트럴 전송하고 연결을 종료할 준비가 되면, 자신의 FIN 세그먼트를 송신측에 보낸다.
- ACK 응답 (송신측에서): 송신측은 수신측의 FIN 세그먼트에 대한 ACK를 보냄으로써 연결 종료를 확정한다. 이 ACK를 수신한 후, 수신측은 연결을 완전히 종료한다.
- TIME_WAIT 상태: 4-way 핸드쉐이크가 완료된 후 송신측은 일정 시간 동안 TIME_WAIT 상태에 머물게 된다. 이는 네트워크 지연으로 인해 마지막 ACK가 수신측에 도달하지 않았을 경우를 대비하여, 필요시 재전송할 수 있도록 하기 위해서이다.
- 그레스이풀 (Graceful) 종료: 이 과정은 TCP 연결이 안전하고 정상적으로 종료될 수 있도록 보장한다. 양쪽 모두가 데이터 전송을 완료하고 연결 종료에 동의해야 연결이 완전히 종료된다.
TCP의 4-way 핸드쉐이크는 연결의 안정적이고 정상적인 종료를 보장하며, 네트워크 리소스를 적절히 해제하는데 중요한 역할을 한다.
[ ▶ Head-of Line blocking in HTTP/1 and HTTP2 ]
TCP (Transmission Control Protocol)의 HOL (Head-of-Line Blocking)은 TCP가 순서대로 데이터를 전송하는 특성에서 발생하는 문제이다. 이 문제는 특히 네트워크에서 패킷 손실이 발생했을 때 두드러지게 나타난다.
[ ▷ Head-of Line Blocking ]
TCP는 데이터를 순차적으로 전송하고, 수신측은 받은 데이터를 순차적으로 처리한다. 각 데이터 패킷은 고유한 시퀀스 넘버를 가지며, 이를 기반으로 순서를 결정한다. 만약 중간에 패킷이 손실되거나 지연되면, 수신측은 이후에 도착하는 패킷들도 처리할 수 없게 된다. 이는 수신측이 손실된 패킷의 재전송을 기다리고 있기 때문이다.
아래와 같은 순서로 문제가 발생할 수 있다.
- 패킷 손실 또는 지연: 네트워크에서 패킷이 손실되거나 지연되면, 수신측은 해당 패킷의 도착을 기다려야 한다.
- 후속 패킷의 대기: 손실된 패킷 뒤에 오는 패킷들은 수신칙에서 처리될 수 없다. 이들은 이미 도착했음에도 불구하고, 손실된 패킷이 재전송되고 수신되기 전까지 대기 상태에서 머무르게 된다.
- 처리 지연: 이로 인해 TCP 연결을 통한 데이터 스트림 전체의 처리가 지연된다. 특히 고속 네트워크 환경에서는 이 문제가 전체 성능에 큰 영향을 줄 수 있다.
[ ▷ Persistent connections and pipelining ]
HTTP는 레이어 4의 TCP를 사용하는 레이어 7 프로토콜이다. HTTP/1.0에서는 기본적으로 Connection: Keep-alive 헤더가 사용되지 않는 한, 단일 TCP 연결을 통해 하나의 HTTP 요청만 전송될 수 있으며 해당 응답이 수신된다. HTTP/1.0에서 영구 연결을 사용하더라도 요청은 연결에서 순차적으로만 이루어질 수 있다. 서버에서 페이지당 많은 리소스를 다운로드해야 하는 경우 이는 성능이 뛰어난 접근 방식이 아니며, 대부분의 브라우저는 RFC에도 언급된 것처럼 도메인당 몇 개의 동시 연결만 지원한다. 이러한 제한으로 인해 웹 개발자는 도메인 샤딩 및 CSS 스프라이트와 같은 기술에 의존하게 된다.
단일 TCP 연결을 통해 하나의 HTTP 요청만 전송되는 문제점은 HTTP/1.1로 변경되면서 Connection: keep-alive 헤더를 별도로 명시할 필요 없이 지속적인 연결을 기본 동작으로 만들었다.
HTTP/1.1은 파이프라이닝도 도입했는데, 이를 통해 단일 TCP 연결을 통해 여러 HTTP 요청을 보내고 해당 응답을 기다리지 않고 전송할 수 있게 되었다.
파이프라이닝은 웹 페이지 로딩 시간 성능을 향상시키지만 HOL Blocking 문제가 있다.
[ ▷ HOL blocking with pipelining ]
파이프라이닝에서는 다양한 장소에 HOL 차단이 발생할 수 있다.
- 파이프라이닝은 클라이언트가 이전 요청이 성공적으로 전송된 후에 후속 요청을 시작하도록 요구한다. 그러나 이러한 요청들은 응답을 기다리지 않고 전송될 수 있다.
- 또한 서버는 요청이 받아진 순서대로 응답을 전송해야 한다.
- 클라이언트가 받은 응답들도 순서대로 처리되어야 한다. 이는 클라이언트와 서버가 파이프라이닝으로 요청가 응답을 항상 순차적으로 처리해야 함을 의미한다.
이러한 요청과 응답의 순서는 클라이언트와 서버가 해당 요청과 응답을 서로 연결하는데 필요하다. 만약 요청이나 응답 중 하나의 처리가 다른 것들보다 오래 걸리거나 재전송으로 인해 지연되는 경우, HOL Blocking이 발생할 수 있다. 이는 다른 요청/응답들이 이전 것들이 완료될 때까지 기다려야 한다는 것을 의미한다. 또한, 이러한 순차적 처리 방식은 특히 중간에 프록시가 있는 경우 파이프라이닝의 구현을 버그가 많고 오류가 발생하기 쉽게 만든다. 이 때문에 거의 모든 브라우저에서 파이프라이닝은 기본적으로 비활성화되어 있다.
HTTP/2는 스트림을 사용한 멀티플렉싱을 도입하여 이 문제를 어느 정도 해결했지만, 완전히 해결하지는 못했다.
[ ▷ Multiplexing in HTTP/2 ]
HTTP/2는 요청 멀티플렉싱을 통해 응용 계층 (L7)에서 HOL Blocking 문제를 해결한다. 그러나 HOL 문제는 여전히 전송 계층 (TCP)에서 존재한다.
HTTP/2는 HTTP의 응용 프로그램 시맨틱을 어떤 방식으로도 변경하지 않는다. HTTP 메서드, 상태 코드. URI 및 헤더 필드와 같은 핵심 개념은 그대로 유지된다. 대신, HTTP/2는 데이터가 클라이언트와 서버 간에 어떻게 포맷되고 (프레이밍) 전송되는지를 변경한다. 이 과정은 전체 프로세스를 관리하며, 새로운 프레이밍 (framing) 계층 내에 모든 복잡성을 숨긴다.
HTTP/2는 동일한 연결 상에서 요청과 응답 메시지를 멀티플렉싱을 통해 교차로 처리할 수 있게 하며, 이는 이전의 파이프라이닝의 제한 사하을 해결한다. 멀티플렉싱은 클라이언트와 서버 간에 요청 및 응답 세거먼트의 양방향 흐름을 명시적인 순서없이 가능하게 한다. 이는 스트림 (Stream)이라는 개념을 도입함으로써 가능해졌다. 스트림은 고통 스트림 ID로 표시되는 단일 요청 / 응답 통신의 논리적 단위이다.
[ ▷ Frames, messages, and streams in HTTP/2 ]
HTTP/2에서의 HOL Blocking을 이해하기 전에, 그 구성 요소와 기능에 대해 이해하는 것이 중요하다.
◎ Frame
프레임은 HTTP/2에서 가장 작은 통신 단위이다. 프레임은 HTTP 헤더나 페이로드와 같은 특정 유형의 데이터를 전달한다. 모든 프레임은 고정된 9 옥텟 헤더로 시작한다. 헤더 필드에는 스트림 식별자 필드 등이 포함되어 있다. 헤더 다음에는 가변 길이의 페이로드가 온다.
◎ Message
메시지는 완전한 HTTP 요청 또는 응답 메시지이다. 메시지는 하나 이상의 프레임으로 구성된다.
◎ Stream
스트림은 클라이언트와 서버 간의 양방향 프레임 흐름이다. 스트림의 몇 가지 중요한 특징은 아래와 같다.
- 단일 HTTP/2 연결은 여러 개의 동시에 열린 스트림을 가질 수 있다. 클라이언트와 서버는 연결 상의 다른 스트림에서 프레임을 전송할 수 있다. 스트림은 클라이언트와 서버 양쪽에서 공유될 수 있다. 스트림은 단일 피어에 의해 설정되고 사용될 수도 있다.
- endpoing 중 하나가 스트림을 close할 수 있다.
- 스트림은 정수 값으로 식별된다. 식별자 정수값은 스트림을 시작한 endpoint에 의해 할당된다.
이와 같이, 각 프레임이 스트림 ID와 연관되어 있기 때문에, 클라이언트와 서버가 HTTP 요청과 응답을 순서대로 처리해야 하는 요구사항이 제거된다. 이로써 HTTP 계층에서의 HOL Blocking 문제는 해결되지만, 이제 TCP 계층으로 이동한다.
[ ▷ HOL Blocking at TCP layer ]
TCP 패킷이 네트워크를 통해 전송될 때 각각 고유한 시퀀스 넘버를 가진다. 그리고 데이터는 수신자에게 순서대로 전달되어야 한다. 만약 패킷 중 하나가 수신자에게 가는 도중에 손실된다면, 손실된 패킷이 재전송되어 수신자에게 도착할 때까지 모든 후속 패킷들은 수신자의 TCP 버퍼에 보관되어야 한다. 이 작업은 TCP 계층 내에서 이루어지므로, HTTP 계층은 TCP의 재전송이나 대기 중인 패킷 버퍼에 대해 알 수 없으며, 데이터에 접근하기 위해 전체 시퀀스를 기다려야 한다. 대신, 소켓에서 데이터를 읽으려 할 때 배달 지연을 경험하게 된다. 이미 수신된 패킷들이 다른 스트림의 완전한 요청/응답 메시지를 형성하고 지연된 패킷을 기다리지 않고 HTTP 계층에 전달될 수 있는 가능성이 충분히 있다. 이러한 효과를 TCP Head-Of-Line Blocking 이라고 한다.
[ 참조 ] : https://web.dev/articles/performance-http2?hl=ko
◎ TCP의 Head-of-Line Blocking
TCP의 Head-of-Line Blocking은 특히 네트워크가 혼잡하거나 불안정할 때 성능 저하의 주요 원인이 될 수 있으며, 이를 해결하기 위한 다양한 방법이 연구 및 개발되고 있다.
◎ Head-of-Line Blocking과 시퀀스 넘버
TCP (Transmission Control Protocol)의 Head-of-Line Blocking 문제는 시퀀스 넘버 (Sequence Number)의 사용과 밀접한 관련이 있다. TCP 시퀀스 넘버는 데이터 패킷의 순서를 정의하고 관리하는데 사용되며, 이 순서대로 데이터가 수신되고 처리되어야 한다.
◎ Head-of-Line Blocking과 시퀀스 넘버
- 순차적 수신 및 처리: TCP는 시퀀스 넘버를 사용하여 데이터 패킷을 순차적으로 수신하고 처리한다. 수신측은 시퀀스 넘버 순서에 따라 패킷을 재조립한다.
- 패킷 손실 시 문제 발생: 만약 특정 시퀀스 넘버를 가진 패킷이 손실되면, 수신측은 그 이후의 패킷들을 처리할 수 없다. 이는 손실된 패킷이 재전성되어 도착할 때까지 후속 패킷들이 대기 상태에 머무르게 만든다.
- 전송 지연: 이러한 매커니즘은 네트워크에서 패킷 손실이 발생했을 때 전체 TCP 스트림의 처리가 지연되는 원인이 된다. 손실된 패킷이 재전송되고 수신되기 전까지는 후속 패킷들이 처리되지 않으므로, 전체 데이터 흐름이 막히게 된다.
◎ TCP의 신뢰성과 성능
TCP는 데이터의 순서와 무결성을 보장하기 위해 시퀀스 넘버를 사용한다. 이는 신뢰성 있는 데이터 전송을 위해 필수적이다. 그러나 이와 동시에 특정 조건에서는 Head-of-Line Blocking 문제를 야기하여 전체 네트워크 성능에 영향을 미칠 수 있다.
HTTP/3 또는 QUIC는 TCP 대신 UDP를 전송 프로토콜로 활용하여 이 문제를 해결한다. 이들은 패킷 손실이 발생하더라도 전체 데이터 스트림의 흐름을 덜 방해하는 방식으로 설계되었다. 이러한 솔루션들은 TCP의 신뢰성은 유지하면서도 Head-of-Line Blocking 문제를 줄이려는 시도들이다.
'네트워크' 카테고리의 다른 글
HTTP 메시지 (1) | 2024.09.27 |
---|---|
HTTP의 진화 (0) | 2024.09.27 |
HTTP 개요 (3) | 2024.09.27 |
TCP Socket Programming (0) | 2024.09.27 |