모든 이야기

수신자는 멀쩡한데 네트워크가 막힐 때: 혼잡 제어

혼잡 제어는 여러 송신자가 공유하는 네트워크 경로의 처리 능력을 넘지 않도록 전송량을 조절하는 기능이다. 수신 버퍼를 보호하는 흐름 제어와 달리, 라우터의 큐와 공유 링크 같은 중간 자원을 고려한다. 수신 컴퓨터가 빠르고 버퍼가 넉넉해도 경로가 혼잡하면 송신량을 줄여야 한다.

공유 링크의 큐와 피드백을 보고 송신자가 혼잡 윈도를 늘리거나 줄이는 그림

혼잡 제어는 경로의 반응을 이용해 공유 자원에 맞는 전송량을 찾아간다.

한꺼번에 보낼 수 있는 양을 찾는다

TCP 송신자는 혼잡 윈도인 cwnd를 관리한다. 이는 아직 확인 응답을 받지 않은 상태로 네트워크에 둘 수 있는 데이터의 양을 제한하는 데 쓰인다. 실제 전송은 수신 윈도와 이미 전송 중인 양 등 다른 조건에도 묶인다. cwnd는 상대가 직접 알려 준 버퍼 크기가 아니라 송신자가 경로의 반응을 보고 조절하는 상태다.

전통적인 TCP 느린 시작은 확인 응답을 받으면서 윈도를 빠르게 늘린다. 이름과 달리 단순한 모델에서는 왕복 시간마다 대략 두 배로 성장할 수 있다. 처음부터 최대 속도로 쏟아붓는 대신 작은 범위에서 출발하지만 증가 방식은 빠르다. 임계값에 도달하면 보다 완만하게 증가하는 혼잡 회피 단계로 넘어간다.

고전적인 AIMD 방식은 혼잡이 없을 때 점진적으로 늘리고, 혼잡을 감지하면 일정 비율로 줄인다. 여러 흐름이 경쟁할 때 자원을 탐색하면서 과부하에서 물러나는 피드백 규칙이다. 손실, 왕복 시간 변화, 명시적 혼잡 통지인 ECN 등은 알고리즘에 따라 서로 다른 방식으로 활용된다.

손실은 언제나 같은 뜻일까

패킷 손실은 혼잡의 중요한 신호일 수 있지만 무선 오류나 경로 변경처럼 다른 원인도 있다. 또한 큐에 오래 머물다가 전달되는 패킷은 손실이 없어도 지연이 크다. 따라서 혼잡 제어의 평가는 처리량뿐 아니라 지연, 손실, 공정성과 안정성을 함께 봐야 한다.

병목 링크가 10Mbps라고 해서 각 TCP 연결이 언제나 정확히 같은 몫을 받는 것은 아니다. 왕복 시간, 알고리즘, 흐름 수와 시작 시점 등이 경쟁 결과에 영향을 준다. 고전적인 윈도 기반 접근에서 왕복 시간이 긴 연결은 같은 윈도로 더 낮은 전송률을 얻을 수 있다. 한 사용자가 연결을 아주 많이 만들면 흐름 단위의 공정성만으로 사용자 단위의 공정성이 보장되지도 않는다.

버퍼를 크게 늘리면 손실 시점은 늦출 수 있으나 큐잉 지연이 커지는 버퍼블로트가 생길 수 있다. 링크 용량을 늘리는 것, 큐를 관리하는 것, 송신자의 증가 규칙을 바꾸는 것은 서로 다른 조정이다. 실시간 응용에서는 평균 처리량이 높아도 긴 지연 꼬리 때문에 품질이 나빠질 수 있다.

혼잡 윈도가 20KiB이고 왕복 시간이 100ms인 단순 모델에서 전송률 상한은 대략 200KiB/s다. 윈도를 두 배로 늘려도 경로의 실제 용량이 그보다 낮으면 같은 비율로 빨라질 수 없다. 측정값과 모델을 연결할 때는 윈도/왕복 시간 추정과 링크 용량 중 어느 조건이 제한하는지를 분리해서 생각해야 한다.

모든 TCP가 같은 고전 알고리즘을 쓰는 것은 아니다. 운영체제와 설정에 따라 손실 기반, 지연 기반, 대역폭 추정 기반 접근 등이 사용될 수 있다. 특정 곡선을 TCP 전체의 영구한 규칙으로 외우기보다, 무엇을 혼잡 신호로 보고 언제 증가하거나 감소시키는지를 설명하는 편이 실제 시스템을 이해하는 데 도움이 된다.

참고 자료

수신자는 멀쩡한데 네트워크가 막힐 때: 혼잡 제어 · ariser