router 는 패킷포워딩(전달) 을 열심히해야되는데 이런거 할 여력이 없다고요. 네트워크 상황을 알아내는 것 자체가 쉬운일이 아니라서 특정 현상을 가지고 짐작할수밖에 없다. 그래서 그 짐작을 가지고 sending을 조절하게 되는데, informal 한 정의를 보면, 너무 많은 양의 전송이 몰려서 데이터가 막히는 것.
그럼 어떤 문제가 일어나? 큐잉 딜레이가 길어지거나, 큐보다 길어지면 데이터가 아예 유실되어버려.
congestion은 왜 발생하고 우리는 어떤 대가를 치러야하는가. toy 예시를 보고 살펴보자.
AB 두명의 센더가 있고 서버가 두대가 있다. 여기서는 가상의 상황으로 하나의 라우터가 무한대의 큐를 가지고 있는거야. 무한정 저장할수 있는 큐를 비현실적으로 가지고 있는거야. 재전송이 이뤄지지 않는다는 가정도 추가할게요. unlimited 니까 loss 가 발생하지 않고 delay만 고려해보자는거죠. bandwidth === r 이라고 했을 때, trhoughput (당ㄴ윗시간당 얼마만큼의 데이터가 전달되는가?) 여기에 나와있는데, 람다인 람다아웃이라고 잇죠. 센딩레이트가 높아질수록 라우터가 받는 양과 속도도 올라가겠죠. 여기서 열심히 빨리 보내면 받는것도 빨리 바등ㄹ거아냐. 그렇게 어느 정도 수준까지는 r/2 까지는 올라갈거야 (서버가 두대니까) 아무리 빠른 속도로 보내든간에 이런 가상의 상황이라면 throughput에 대해서는 악영향이 없는거네. 받는 속도 측면에서는 괜찮은데. 딜레이를 볼까? 딜레이가 기하급수적으로 늘어나서 무한대에 수렴해.
센더가 데이터를 보내고, 데이터가 서버까지 도착하는데까지 걸리는시간이 딜레이라고 보면돼요. 딜레이가 무한대로 늘어나게 된다고 점점. 큐가 쭉 쌓일테니까. 여기서 보게되면 이런 단순하고 비현실적인 가정에서 봤을 때도, 현실보다 훨씬 좋은 상황이잖아 재전송도 없고, 큐도 무한대인데도, 데이터를 너무 빨리 전달하는 상황을 접하게 되면 delay측면에서 엄청난 피해가 있는거야. 쉽게 추측할 수 있는 치러야할 피해고. 이번에는 좀더 현실적인 가정으로 라우터가 이번에는 제한된 큐사이즈를 가지고 있다고 칩시다. 센더는 티씨피처럼 타임아웃, 이 되면 재전송을 합니다. 그럼 람다 인 은 애플리케이션이 보낸 데이터 속도고 람다 프라임2는 tcp에서 보내는 데이터 속도, 양이라고 생각하면돼요. 재전송해야될 데이터까지 포함된거죠.
역시이제 방금말했던 상황에서는 r/2 가 되어요. 버퍼가 비었을 대만 알아서 보낸다고 했으니까. 이번 가정은 뭐냐면, 패킷 유실이 가능한데, 이번 가정은 패킷 유실이 되면 그 때만 재전송을 한다. 내려오는것보다 재전송한것까지 포함하면 더 많은 데이터가 가게되겠지. 그럼 이런 그래프가 나와요 (꼬다리가 필렛된 꺾은선그랲흐..)
기존 데이터 양보다 더많은 양이 나간단 얘기죠. 컨제션이 일어났기 때문에, 드랍이 된걸 매꾸려고 더 많은 양이 나감. 이 트렌스 미션을 위해서 우리는 throughput을 손해본다는 이야기에요. 실제 전송되는 데이터는.
네트워크의 일부는 재전송에 쓰이니까 재전송에 쓰이는 만큼은 손해보는거야. 컨제스쳔이 일어나면 손해보고, 손해보면 loss가 많이일어나고, 재전송을 하면할수록 악순환이 일어나는거야. 패킷 유실이 일어날 수 있는데, 확신없이 타임아웃으로 이 유실을 알아낸다는 이야기는 premature 타임아웃같은 더 안좋은 상황이 일어나는거야. 실제로 유실되지 않은 애들에 대해서도 timeout때문에 불필요한
라우터를 여러개 지난다음에 마지막 라우터에서 죽어버리면 upstream을 왔다갔다하면서 네트워크에 손해를 끼치고 죽어버리는 거야 차라리 일찍 죽어버리는 것이 손해를 최소화하는 방법이에요. 그래서 센더쪽을 upstream이라고 하고 리시버 쪽을 downstream이라고 해요 업스트림쪽에서 자원을 다 소비하고 다운ㅅ스트림에서 로스되어버리는 것을 최소화 해야해요.
네트워크 상황이 안좋아졌어. 그럼 보내는데 안오면 더보냈죠 지금까지 배운건. 우리가 실제적으로 보내야되는 data 는 2kb라고 하면 보내 근데 답이 안와 그럼 재전송 해야지 재전송 계속 보내! 재전송! 답이안와! 재전송!! 그럼 네트워크상황을 보고 또 보낼지 말지 판단을 해야된다고. 네트워크상황을 판단하는 방법은 두가지가있을거예요. 나랑 저 끝에 있는애랑 짐작하는 방법이 있을거고, 두번째로는 중간에 있는 라우터들이 정보를 보내는 방법이 있으거예요. 근데 라우터는 그런거 봰ㄹ 능력이 없어. 그런 도움을 받지 않고, 양끝에 있는 피드백을 통해서 내부를 짐작하는 방식을 취해요.
세그먼트보냈어요. 근데 ack왔어. 드랍되지 않고 왔다갔다 한거지? 그럼 네트워크는 내가 원하는 세그먼트 보낼정도는 된다는거지? timeout 됐어. 그럼 뭔가 문제있다.라는 피드백만 가지고 현재 tcp는 네트워크 상태를 짐작해요. 좀더 구체적으로 이야기해봅시다. 그럼
x축이 시간축이고 y축이 윈도우 사이즈, ack잘 왔어. 그럼 네트워크 좋다는거지. 그럼 10개 보냈어. 그럼 11개, 12개, 13개, 그러다가 14개 보냈는데 막혔어. 그럼 딜레이 갑자기 늘어난다고, 막혔을 때는 뒤로 확 물러서야돼, 절반으로 줄여. 도메인 양을 늘릴때는 조금씩 늘리고 줄일때는 절반만큼. 이게 반복되는거야. additive increase multiplicative decrease
다양한 tcp를 활용한 통신을 보면 다 이런식이에요. 최대한 많은 양 쏟아붓고 싶은데, 막히면 확 돌아가는거야 그래서 되게 조심스럽게 찾아가는거야. 그 지점을 찾아가는 과정인데, 적절한 bandwidth 찾느거야. 여기가 시작점이죠? 우리가 알고 잇는 윈도우 사이즈가 되겠습니다. 이거슨 내트ㅊ워크 상황에 다라서 달라진다. 한꺼번에 윈도우 사이즈만큼 보낼수있잖아 이걸 보내고 애크를 받은 다음에 조금씩 늘려서 보낼수잇는거야. 라운드 트립 (왔다갔다)한 이후에 보낼 수 있는거잖아.
윈도우사이즈이거 청ㅁ에 몇으로 시작해야 안전할까요? 엄청 크게 설정해서 부었는데 막혔다. 그럼 네트워크 공공자원을 방해시키는거니까, 피해를 끼치는 거라고. 그래서 우리는 하나부터 시작해. 슬로우스타트로 하나 보내. 애크 잘왔어. 2개 보내, 4개보내.. 하나씩 exponential 하게 증가해요. 경험적인 수치로 ssthreshhold값이 정해져있어요. 특정값이 지나면 리니어하게 하나씩 증가해요.
어느포인트에 ㄴ네트워크에서 감당할수있는 최소한의 값이 있을거라고, 최소한 어느정도까지는 경험적으로 아는거야. 그 전까지는 보폭을 막 확확 exponential 하게 증가하다가 그 지점이 지나면 리니어하게 조심조심 증가하는거야. 그러다 문제가 터졌어. 패킷 로스가 났어(애크가 안왔던지(==타임아웃), 3 듀플리케이티드 애크) 둘중에 하나에요 무조건~ 3 dup ack예요. 하지만 이 둘은 전혀 다른! 네트워크 상태에대한 피드백이에요. 어떤차이?
패킷 10개 보냈는데 그 중에 하나만 안왔구나, 애크가 계속 오고있긴 하니까. 라고 생각할 수 있어. 근데 타임아웃은 3dup ack도 없다는 거지. 타임아웃 될때까지 애크 하나도 안왔다는 거야. 아무것도 살아남지 못한거라고. 네트워크 상황이 아주 심각하다는 걸 알수있지. 그래서 3듚앸은 그냥 겸손하게 다시 시작해볼까 하고 생각하는거야.
타임아웃이든 3어쩌구든 현재 윈도우 값의 절반으로 줄이고 다시 시작하는게 초기 버전이었으나, 르노는 처음부터 시작할 필요없어. 스레쉬홀드값을 현재 윈도우값의 절반으로 줄이고 여기서부터 리니어 증가, 하지만 르노도 타임아웃이었으면 처음부터 다시 조심조심 증가시킴. 슬로우스타트! 말이 슬로우스타트지 exponential 하게 증가하기때문에 슬로우아님. 초기시작하는 값이 아주 안전할 만큼 작기 때문에 붙은말임. 초기 버전인 타오와 르노가 어떻게 다른지 이해를 하고 있어야해용. 타오라는 도시랑 르노라는 도시가 어떻게 다르냐면 캘리포니아와 네바다사이의 도시인데, 이 이후에 tcp 버전은 다 도박도시의 이름이 붙었어요. 이 이후의 버전읜 베가스예요 ㅋㅋ 이름 붙이는 것은 디자이너 마음이니까~ 여러분이 만들면 강원으로 지으세요 ^.^