Post

HTTP 완벽 가이드

목차


HTTP 완벽 가이드 책 리뷰

telnet으로 HTTP 통신하기

telnet 프로토콜 및 여러가지 CLI 툴로 HTTP Raw Request 하는 방법 정리
https://dev.iasdf.com/wiki/linux/http_cli

TCP 커넥션으로 인한 지연

나는 HTTP의 연결을 끊지 않고 유지하는 이유가
연결을 끊었다 다시 요청할 경우, 3-way/4-way handshake 인해 주로 발생하는 것이라고 생각했다.

그러나 약 1970년부터 연구되어 1983년에 개발된 글을 적고 있는 현재 기준으로 약 40년의 역사를 지닌 고인물 프로토콜 답게 TCP 프로토콜은 신뢰성 확보를 위해 내부적으로 여러가지 알고리즘이 도입되어 있는데, 이러한 알고리즘에 의해서도 지연이 발생하는 것을 알게 되었다.

  • delayed ack (확인 응답 지연)
    • http://www.ktword.co.kr/test/view/view.php?no=3242
    • TCP의 경우 신뢰성 확보를 위해 ACK 패킷을 전송해야 함. 즉 아래와 같은 통신이 사용됨
      1
      2
      3
      4
      5
      
        C              S
        | SYN ->       |
        |       <- ACK |
        |       <- SYN |
        | ACK ->       |
      
    • ACK 패킷만 바로 보내게 되면 ACK 패킷을 보내기 위한 TCP 헤더 등을 추가로 송신해야 하며, ACK 패킷을 따로 보내게 될 경우 오버헤드가 발생할 수 있음.
    • SYN 패킷을 받았을 때, ACK 패킷을 바로 전송하는 것이 아닌, 0.1초 혹은 그 이상의 대기시간을 주어 서버의 SYN 요청과 ACK 패킷을 함께 보내면 부하를 줄일 수 있음. (piggy-back 방식)
      1
      2
      3
      4
      
        C              S
        | SYN ->       |
        |   <- ACK/SYN |
        | ACK ->       |
      
    • 안타깝게도, 요청과 응답, 딱 두가지의 통신 방식만 있는 HTTP는 이러한 ACK 패킷이 다음 SYN 패킷에 편승할 기회를 감소시킴.
  • slow start
    • 클라이언트 또는 서버의 네트워크 상태를 모르니, 혼잡이 발생하지 않도록 커넥션이 처음 발생했을 때 패킷을 전송하는 양을 제한하고, 이를 천천히 늘려나가며 네트워크 혼잡을 제어함.
    • 이를 TCP 혼잡 제어라고 하는데, 이 때문에 TCP의 커넥션이 막 연결될 당시에는, 혼잡 제어 알고리즘으로 인해 이미 연결된 알고리즘에 비해 속도 저하가 발생함.
    • 즉, HTTP의 커넥션을 유지하지 않으면, 새로운 요청을 진행할 때메다 tcp 커넥션을 연결하고 끊기 때문에, slow start로 인해 지연이 발생할 수 있음.
  • Nagle(네이글) 알고리즘과 TCP_NODELAY
    • 매우 작은 데이터를 보내야 하는 경우, (예를 들어 1~10byte 정도) Data의 내용보다 이 내용을 보내기 위한 TCP 헤더의 정보가 더 크다.
    • 따라서 이러한 작은 패킷들을 모아, 묶어서, 전체 크기의 세그먼트를 전송할 수 있을 때까지 패킷의 전송을 지연시킬 수 있음.
      • MTU(Maximum Transmission Unit) 사이즈는 일반적으로 1500 byte 이므로, MSS(Maximum Segment Size)는 TCP 헤더와 IP 헤더의 길이를 제외한 1460 byte 이다.
    • 네이글 알고리즘은 delayed ack와 함께 쓰일 경우 문제를 발생시킨다.
      • delayed ack는 확인 응답을 100~200 밀리초 지연시키는데, 네이글 알고리즘은 확인 응답이 도착할 때 까지 데이터 전송을 멈추기 때문에 서로 상반되는 제약조건을 가지고 있다.
    • 또한 네이글 알고리즘은 MSS 사이즈의 패킷을 채우지 못하는 크기가 작은 HTTP 메시지의 경우, 앞으로 생길지 알 수 없는 추가적인 데이터를 기다리며 지연시킬 것이다.

    • 따라서 HTTP 어플리케이션은 성능 향상을 위해 TCP_NODELAY 옵션을 주어, 네이글 알고리즘을 비활성화 하기도 한다.
      • 이 설정을 진행했다면 작은 크기의 패킷이 많이 생기지 않도록 큰 크기의 데이터를 만들어야 한다.
  • TIME-WAIT 누적, 포트 고갈
    • TCP는 4way handshake 이후에도 연결을 바로 종료하는 것이 아니라, TIME_WAIT을 통해 잠시 대기 상태에 들어간다.
    • A가 FIN을 보내고 B가 ACK, FIN을 보낸 뒤, A가 ACK를 보내고, A 또한 연결을 바로 끊는 것이 아니라 TIME_WAIT 상태에 진입한다.
      • 이유인 즉, 혹시 마지막에 B에게 보낸 ACK 메시지가 도착하지 않았을 경우, B는 A에게 다시 FIN/ACK 메시지를 보내게 된다.
      • A는 TIME-WAIT 상태에서 기다리다가 FIN/ACK 메시지를 받게 되면 TIME-WAIT 상태에서 빠져나와 B에게 다시 ACK 메시지를 보내고, 다시 TIME-WIAT 상태로 돌입한다.
    • 즉, 먼저 연결 종료를 요청할 경우 TIME-WAIT 상태에 들어간다.
    • 마지막 ACK 패킷이 전송되었는지를 확인하기 위해 거치는 작업. (혹시 모를 전송 실패에 대비하기 위해 TIME-WAIT이 존재)
    • TIME WAIT이 설명된 문서 : https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        A              B
        | FIN ->       |
        |       <- ACK |
        |       <- FIN |
        | ACK ->       |
        |(TIME-WAIT)   | (소켓 소멸)
        |(TIME-WAIT)   |
        |(TIME-WAIT)   |
        |(TIME-WAIT)   |
        |(TIME-WAIT)   |
        |(TIME-WAIT)   |
        |(소켓 소멸)     |
      
    • 어느 쪽에서 FIN 패킷을 먼저 보내는가에 따라 발생 케이스가 달라질 수 있다.
    • TIME WAIT 과 포트 고갈로 인한 문제 발생 사례 : https://tech.kakao.com/2016/04/21/closewait-timewait/
    • 일반적인 상황에서는 발생하지 않을 가능성이 크나, 성능측정과 같이 제한적인 컴퓨터 대수로 많은 요청을 진행할 경우, TIME_WAIT 의 누적과 포트 고갈로 인해 문제가 발생할 수 있음.
    • 이러한 문제를 해결하기 위해 TIME WAIT 상태의 소켓을 재사용하는 net.ipv4.tcp_tw_reuse 옵션 또는 net.ipv4.tcp_tw_recycle 옵션을 사용할 수 있다.
    • 물론 이 외에도, 많은 양의 커넥션을 맺어두거나 대기 상태로 있는 제어 블록이 많아지는 상황은 조심해야 함.
This post is licensed under CC BY 4.0 by the author.