TCP segment 가 전송되지 않는다면 어딜 의심할까?

A서버에서 B서버로 대용량 데이터를 전송하는 네트워크 프로그래밍을 하나 한다고 치자.
이런 저런 삽질 끝에 프로그램을 한 쌍 — 보내는 쪽과 받는 쪽 — 만들었다. 이제 이 프로그램을 실험해 볼 차례다.

실험 결과, A 서버에서 네트워크 send() 호출하는 게 충분히 빠르지 않은 것 같다 – 사실 정말 그런진 모르겠고, send-queue가 너무 빨리 늘어나는데 반해, 실제 네트워크 사용률도 그리 높지 않아서 어느 쪽이 문제인지 모르겠다고 쳐보자.

어디가 문제라고 판단해야 할까? 근데 설상가상으로 B 서버에 직접적으로 붙어서 디버깅하거나 할 순 없는 상황이라고 치자(…).

A? B? 어느 쪽을 의심해야 할까? 그리고 그 판단의 근거는?

이제 이걸 판단할 근거를 찾아보자.

 

Plan A: TCP segment 를 캡쳐해서 까본다

TCP segment 는 항상 다음과 같은 window 안에서 전송된다.

TCP_Sliding_Windows

이 구조를 sliding window라고 한다.[1] 여기서 제일 중요한 부분이 advertised window 부분이다. 이 값은 받는 쪽의 TCP segment의 header에 있는 window 필드를 통해 전달된다. 모든 전송 관련된 메시지는 이 window를 기준으로 전송된다. 만약 받는 쪽에서 ACK을 보내면 이 window의 오른쪽이 ACK된 마지막 패킷 + window의 위치로 전진한다. 물론 retransmission을 원하는 경우 그냥 같은 값이 올 수도 있다. 그리고 보내는 쪽은 advertised window 안에 있는 segment 만 보낼 수 있다.

즉, 마지막 ack #부터 시작해서 ack # + window 까지 전송할 수 있는 상태다. 그리고 이 window는 0일 수 있다. 즉, 받는 쪽에서 더 이상 segment를 못 받는 경우 이걸 0으로 설정하고, 차후에 공간이 생기면 window update 메시지를 통해 이 값을 증가시킨다 — 같은 ack #에 window 값만 증가시켜서 보낸다.

이걸 가지고 서버 A와 B 중 어느 쪽이 병목인지 판단할 수 있다. 우선 이런 ACK segment의 header를 까봐야 하니 WireShark 같은 툴로 TCP를 캡쳐하고, B 서버의 advertised window와 ack 된 범위를 확인하면 된다.

  • 만약 크기 0인 window만 보내고, advertised window 크기를 늘리지 못하면, 이건 받는 쪽(서버 B)가 동작하는 방식이나, 구현체 자체의 성능 문제다. 즉 B가 TCP segment를 윗단의 응용 프로그램에 보내지 못해서 – 즉 윗 단이 느려서 — A는 보낼 여력이 있는데 B가 처리 못하는 것이다.
  • 반대로 advertised window 에는 공간이 있는 경우(can be sent로 표시된 부분이 0보다 큼)0) A가 느려서(?) 못 보내는 문제다.

근데 이거 생각 외로 잘 안 될 때가 있다. 왜냐하면 속도 문제를 고민할 정도의 상황이면 캡쳐 툴이 이걸 잘 캡쳐하지 못하고 일부를 놓칠 수 있고, 일일이 까보는 것도 그렇게 쉽진 않다. 그럼 좀 더 프로그래밍 적인 방법을 찾아보자.

 

Plan B: B 서버를 흉내 내는 툴을 짜고 패킷을 받고 바로 버린다

별도의 처리 없이 TCP 스트림을 받아서 버리는 툴(TCP sink)을 만든다. A-B 연결의 도입부분만 적당히 흉내(!)내고, 그 이후에는 받고 무시하는 프로그램을 짜자.
그리고 실제 B 서버 대신 이 TCP sink에 접속해서 속도가 얼마나 나오나 보면 된다. 실제로 전송되나 여부는 TCP sink 쪽에서 받은 bytes 수만 세면 된다.[2]

 

하여튼 내 경우엔 Plan B로 문제의 원인을 찾았다. 모처에 있던 B 서버의 성능 문제… 사실 Plan A로 해결하고 싶었지만, Windows 용 WireShark로 전부 다 캡쳐하질 못하더라. 이건 원인을 잘 모르겠음; 그냥 WinPcap이 구리다?

  1. 자세한 사항은 TCP/IP Illustrated Vol. 1, Chapter 20. TCP Bulk Data Flow 참조 []
  2. 데이터 무결성은 TCP 자체를 믿으면 된다. 정말 민감한 데이터가 아닌 이상… 그리고 그 경우엔 응용 프로그램 단에서 적당한 CRC 등을 이용할 생각을 하자. []

Published by

rein

나는 ...

6 thoughts on “TCP segment 가 전송되지 않는다면 어딜 의심할까?”

  1. 예상되는 글이 올라오니 기쁘군 (앙?!)

    근데 WireShark 같은 S/W Tool은 생각보다 좋은 성능이 안나오는듯 함. 역시 H/W가 진리라고 생각됨.

  2. 이 경우에는 text mode인 tshark로 패킷 덤프만 떠놓고 느긋하게 덤프를 분석하시면 됩니다.. pcap 덤프 해석은 직접 하셔도 되고 kraken pcap으로 하시면 프로그래밍으로 분석하기가 더 편하죠.. 그리고 원래 pcap 구조가 패킷 하나씩만 커널에서 받아오게 되어있어서 고속 전송 시에는 packet loss가 쉽게 나구요

    1. tshark 좋네요. 이거 써봐야겠네요. 사실 크라켄을 쓰는게 더 좋을것같지만(…).

      문제가 고속 전송 시에 주로나서 그런지 좀 뼈아팠습니다(?).

  3. pcap 자체가 빠지는 현상은…
    오래전일이라(2004년정도?) 지금은 상관없을수도 있지만;;;;

    좀 저가형 LAN 카드들이 과부하가 걸리믄 제대로 동작하지않는거 같더라구요…
    Realtek으로는 안되고 3COM으로는 되더라는 -_-;;;;;

Leave a Reply