티스토리 뷰
이번 포스팅에서는 HTTP 완벽가이드, 네트워킹과 웹 성능 최적화 기법, 리눅스 커널 이야기, 와이어샤크를 활용한 실전 패킷 분석 책을 활용하였습니다.
4장 Connection 관리
2. TCP 오류 복구 기능 (신뢰성)
* TCP 3 way handshake는 왕복시간 한번만큼의 latency를 발생시킨다.
* TCP Slow start는 connection이 새로 만들어질 때 항상 발생한다.
* TCP Flow control과 Congestion control은 모든 Connection의 처리량을 조절한다.
* TCP 처리량은 현재 cwnd(Congestion Window) size에 의해 결정된다.
1) 흐름제어
흐름제어는 송신자가 수신자에게 처리하지 못할 만큼의 많은 데이터를 전송하는 것을 미리 방지하는 메커니즘이다. 수신자가 데이터를 받지 못하는 경우는 보통 수신자가 다른 데이터를 처리하고 있거나, 밀려있는 데이터가 많거나 버퍼공간을 충분히 지정해주지 않는 경우다. 이러한 문제를 해결하기 위해 양쪽의 TCP 커넥션이 각각 자신의 receive window(rwnd)를 통지하여 수신데이터를 저장할 버퍼 공간의 크기를 서로에게 알려준다. 이 버퍼 공간은 데이터 처리를 기다리는 응용 계층 프로토콜에 스택을 꽉 채울때까지 데이터가 임시적으로 저장되는 공간이다. 따라서 전송 호스트는 한 번에 window size 필드에 명시된 데이터 양 만큼만 보낼 수 있다.
window size를 조정하는 프로세스는 매우 명확하지만, 완벽한 것은 아니다. 데이터가 TCP 스택에 수신될 때마다 ACK가 생성되고 반복적으로 보내지지지만 수신자의 버퍼에 있는 데이터가 항상 즉시 처리되는 것은 아니기 때문이다. window size를 재조정하는 프로세스로 zero window 전송을 통한 데이트 흐름을 중지하는 방법과 TCP sliding window 등의 두가지 방법을 사용한다.
(1) zero window 전송을 통한 데이터 흐름 중지
메모리 부족, 처리능력의 부족 또는 다른 문제로 인해 서버가 클라이언트로부터 보내온 데이터를 처리할 수 없는 경우 서버는 크기가 0인 window를 보낼 수 있다. 클라이언트가 이 패킷을 수신하면 데이터 전송은 중지되지만, keep-alive 패킷의 전송을 통해 서버와의 연결은 유지되며, 서버 측 receive window의 상태를 점검하기 위해 일정 간격으로 패킷을 보낸다.
(2) TCP Sliding window
위의 캡쳐를 보면 window size가 8760 -> 5840 -> 2920 바이트로 감소되다 0이 된다. 이 후 Windwo Update 패킷이 수신되면 다시 데이터를 수신할 수 있게 된다.
(3) Window Scaling
https://tools.ietf.org/html/rfc1323#page-8
원래의 TCP spec에서는 rwnd를 지정할 때 16 비트를 할당한다. 이는 송신자와 수신자가 지정할 수 있는 receive window size의 최대치가 65,535 바이트로 정해져있음을 의미한다. RFC 1323에 기술된 TCP window scale option을 사용하면 rwnd를 1 기가바이트까지 늘릴 수 있게 해준다. 최근 대부분의 플랫폼에서는 기본적으로 활성화되어 있다.
2) 혼잡제어
혼잡붕괴(Congestion collapse)란, Speed mismatch(1G input port 1개에서 100Mbps output port 1개로 나갈 때)거나 여러 port에서 입력된 트래픽이 하나의 port로 집중(1G input port 2개에서 1개의 1G output port으로 나갈 때)되는 등의 상황에 발생한다. 전자의 경우 buffering은 output port의 buffer(output queue)에서 발생하며, 후자의 경우엔 input/output queue 모두 발생할 수 있다. 후자의 경우 port별 경쟁 상황이 발생하는데 queue의 크기가 작으면 buffer overflow에 의해 packet drop이 발생하여 TCP 송신자가 DUP_ACK를 연속 3회 수신하게 된다. 반면, queue의 크기가 크면 queue에서 대기하는 buffering delay가 증가하여 TCP retransmission timeout이 발생한다. 그리고 이 두 경우에 TCP congestion을 감지하고 혼잡 제어 동작을 수행한다.
- TCP retransmission이란,
호스트가 패킷을 재전송하는 기능은 TCP가 제공하는 가장 기초적인 오류 복구 기능이며, 패킷 손실을 방지하게 설계돼 있다.
패킷 손실은 애플리케이션 오작동, 라우터의 과부하 트래픽, 일시적인 서비스 정지 같은 여러가지 상황에서 발생할 수 있다.
패킷 재전송 여부에 대한 주요 메커니즘은 재전송 타임아웃(RTO, Retransmission Timeout)값을 갖는 재전송 타이머를 이용하는 방법이다. 패킷이 TCP를 이용해 재전송될 때마다 재전송 타이머가 동작하고, 정상적으로 ACK 패킷을 받으면 정지한다. 이 때 패킷 전송과 ACK 패킷 수신 사이의 시간을 왕복 시간(RTT, Round-Trip Time)이라고 하며, 이 왕복시간들의 평균을 최종 RTO 값으로 결정한다. 최대 재전송 시도 수는 송신 운영체제의 설정에 따라 다르지만, 기본적으로 윈도우는 최대 5회, 리눅스는 15회가 디폴트 값으로 설정할 수 있다.
> https://tools.ietf.org/html/rfc2001
TCP Congestion Control에는 대표적으로 slow start, congestion avoidance, fast retransmit, fast recovery 등 4가지 방법이 있다.
(1) Slow Start
클라이언트와 서버간의 허용량을 가늠하는 유일한 방법은 실제로 데이터를 교환하면서 허용량을 측정하는 것 뿐이다. 이것이 Slow Start가 하는 일이다. 우선 서버가 각 TCP 커넥션마다 새 혼잡윈도(cwnd)를 만들고 그 값을 시스템에서 정해진 안전한 수치로 설정한다.
cwnd: 클라이언트로부터 응답확인(ack) 신호를 받기 전에 송신자 측에서 지정하는 최대 송신 데이터량
cwnd는 송신자와 수신자 간에 값이 교환되거나 서로 통지되지 않는다. 송신자와 수신자 사이에서 이동중인 데이터의 최대치는 rwnd와 cwnd 값 중 작은 값이 된다.
최적의 cwnd값을 알아내는 방법은 (매 커넥션마다 수동으로 조정하지는 않고,) ACK 패킷을 받으면서 점점 윈도 사이즈를 늘려간다.
cwnd size는 항상 2의 배수로 증가하는 것은 아니라 maximum sender mss 크기 1만큼 증가한다. (https://tools.ietf.org/html/rfc5681https://lwn.net/Articles/427104/,"During slow start, a TCP increments cwnd by at most SMSS bytes for each ACK received that cumulatively acknowledges new data")
receive window size나 send window size는 모두 byte 단위이나, cwnd (congestion window) size는 segment 수를 단위로 한다. 여기서 segment란 TCP header를 제외한 TCP payload 크기 즉, TCP MSS를 의미한다.
혼잡 윈도 크기를 증가시키는데 걸리는 시간을 단축시키기 위해서는 클라이언트와 서버간의 왕복시간을 줄이거나 초기 혼잡윈도크기 값(intial cwnd)을 늘릴 수도 있다. (최근의 리눅스커널은 initial cwnd size를 10 segment (lw 10)로 설정되어 있다. https://tools.ietf.org/html/rfc6928)
(2) Congestion Avoidance
혼잡 회피에서 암묵적으로 판단하기에 패킷 손실이 일어났다는 것은 네트워크 혼잡이 일어났다는 신호다. 이동 경로의 어딘가에서 정체가 일어난 링크나 라우터가 패킷을 누락시켰을 것이다. 그래서 네트워크에 부담을 덜어주고 더 이상의 패킷 손실을 막기 위해 윈도 사이즈를 조정해야 하는 것이다.
Packet loss가 감지되면, 바로 이전 Congestion window size를 ssthresh 값으로 설정하고 이후에 congestion avoidance 단계에서 그 ssthresh 값으로부터 segment를 하나씩 증가시키면서 network congestion이 발생하는 지점을 찾는다. packet loss가 발생하면 다시 ssthresh 값을 직전 cwnd의 절반으로 줄이고 다시 slow start를 수행한다. (<그림1>을 참조하자)
그런데 packet loss가 발생했을 경우 이전까지 TCP 송신자는 매번 retransmission timeout(RTO)가 발생할 때까지 기다려서 packet loss를 감지하였다. 이에 대한 대안으로 Fast Retransmission과 Fast Recovery가 제시되었다.
(3) Fast Retransmission & Fast Recovery
Network에서 packet loass가 발생한 사실을 RTO가 아닌 연속 3회 DUP_ACK로 인지하게 될 경우 (<그림1>의 4번, Fast Retransmission) 이전처럼 cwnd를 초기값부터 다시 slow start를 하지 않고 현재의 절반으로 줄인 후에 congestion avoidance를 수행해서 빠르게 packet loss가 발생했던 cwnd 직전까지 찾아간다(Fast recovery).
- 중복 ACK (DUP_ACK)란, 수신자가 잘못된 패킷을 받았을 때 보내는 TCP packet이다. TCP에서는 데이터가 보내진 순서대로 받아 재조립할 수 있게 헤더내에 있는 일련번호와 ACK번호 필드를 이용한다.
'Infra Structure > .system' 카테고리의 다른 글
HTTP 완벽가이드 스터디 #4 -d Keep-Alive (1) | 2019.09.16 |
---|---|
HTTP 완벽가이드 스터디 #4 -c TCP 성능 (0) | 2019.08.25 |
HTTP 완벽가이드 스터디 #4 -a TCP (0) | 2019.08.25 |
HTTP 완벽가이드 스터디 #3 HTTP 메시지 (0) | 2019.08.18 |
HTTP 완벽가이드 스터디 #2 URL과 리소스 (0) | 2019.08.11 |