커넥션 관리 - TCP 커넥션과 성능

커넥션 관리 - TCP 커넥션과 성능

목차
  1. HTTP는 어떻게 TCP 커넥션을 사용하는가
  2. TCP 커넥션의 지연, 병목, 막힘
  3. 병렬 커넥션, keep-alive 커넥션, 커넥션 파이프라인을 활용한 HTTP의 최적화
  4. 커넥션 관리를 위해 따라야 할 규칙들

1. TCP 커넥션

  • 전 세계 모든 HTTP 통신은, 지구상의 컴퓨터와 네트워크 장비에서 널리 쓰이고 있는, 패킷 교환 네트워크 프로토콜들이 계층화된 집합인 TCP/IP를 통해 이루어진다.

웹 브라우저가 TCP 커넥션을 통해서 웹 서버에 요청을 보낸다.

1
https://feel5ny.github.io/index.html
  1. 브라우저가 feel5ny.github.io 라는 호스트 명을 추출한다.
  2. 브라우저가 이 호스트 명에 대한 IP 주소를 찾는다.
  3. 브라우저가 포트 번호 80을 얻는다.
  4. 브라우저가 185.199.111.153의 80포트로 TCP 커넥션을 생성한다.
  5. 브라우저가 바로 HTTP GET 요청 메세지를 보낸다.
  6. 브라우저가 서버에서 온 HTTP 응답 메세지를 읽는다.
  7. 브라우저가 커넥션을 끊는다.

1.1 신뢰할 수 있는 데이터 전송 통로인 TCP

  • HTTP 커넥션은 몇몇 사용 규칙을 제외하고는 TCP 커넥션에 불과하다.
  • TCP 커넥션의 한쪽에 있는 바이트들은 반대쪽으로 순서에 맞게 정확히 전달된다.

1.2 TCP 스트림은 세그먼트로 나뉘어 IP 패킷을 통해 전송된다.

  • TCP는 IP 패킷 (IP 데이터그램)이라고 불리는 작은 조각을 통해 데이터를 전송한다
  • HTTP는 프로토콜 스택에서 최상위 계층이다.
  • HTTPS에는 TLS 혹은 SSL이라 불리기도 하며 암호화 계층이 있다.
  • HTTP 메세지를 전송하고자 할 경우,
    TCP 커넥션을 통해서 메세지 데이터의 내용을 순서대로 보낸다.
  1. TCP는 세그먼트라는 단위로 데이터 스트림을 잘게 나누고
  2. 세그먼트를 IP 패킷이라고 불리는 봉투에 담아서
  3. 인터넷을 통해 데이터를 전달한다.
  • 이 모든 것은 TCP/IP 소프트웨어에 의해 처리되며,
    그 과정은 HTTP 프로그래머에게 보이지 않는다.
  • 각 TCP 세그먼트는
    하나의 IP 주소에서 다른 IP 주소로
    IP 패킷에 담겨 전달된다.

IP 패킷이 포함하는 것.

  1. IP 패킷 헤더 (20byte)
  2. TCP 세그먼트 헤더 (20byte)
  3. TCP 데이터 조각

패킷 구조는 아래와 같다.

그림출처

IP 헤더TCP 헤더는 아래와 같다.

그림출처

1.3 TCP 커넥션 유지하기

  • 컴퓨터는 항상 TCP 커넥션을 여러 개 가지고 있다.
  • TCP는 포트 번호를 통해서 이런 여러 개의 커넥션을 유지한다.
  • TCP 커넥션은 4가지 값으로 식별한다.
  1. 발신지 IP 주소
  2. 발신지 포트
  3. 수신지 IP 주소
  4. 수신지 포트

4가지 값으로 유일한 커넥션을 생성한다.
4가지 커넥션 구성요소를 똑같이 가리키고 있는 커넥션은 있을 수 없다.


2. TCP의 성능에 대한 고려

  • HTTP는 TCP 바로 위에 있는 계층이기 때문에
    • TCP의 성능이 문제가 될 경우 HTTP 트렌젝션 성능에 영향이 있다.
  • 때문에 TCP 프로토콜 내부를 알아본다.

2.1 HTTP 트랜잭션 지연

  • 트랜잭션을 처리하는 시간은
    TCP 커넥션을 설정하고, 요청을 전송하고, 응답 메세지를 보내는 것에 비하면
    상당히 짧다는 것을 알 수 있다.
  • 대부분의 HTTP 지연은 TCP 네트워크 지연 때문에 발생한다.
    (클라나 서버가 많은 데이터를 내려받거나, 복잡하고 동적인 자원들을 실행하지 않는 한)
  1. 클라이언트는 URI에서 웹 서버의 IP 주소와 포트 번호를 알아내야 한다.
    • 만약 호스트에 방문한 적이 없으면 DNS 인프라를 사용하여 IP 주소로 변환하는데 수십 초의 시간이 걸릴 것이다. (DNS 캐시가 없을 경우)
  2. 클라는 TCP 커넥션 요청을 서버에게 보내고, 서버가 커넥션 허가 응답을 회신하기를 기다린다.
    • 커넥션 설정 시간은 새로운 TCP 커넥션에서 항상 발생한다.
  3. 커넥션이 맺어지면 클라는 HTTP 요청을 새로 생성한 TCP 파이프를 통해 전송한다.
    • 웹 서버는 데이터가 도착하는 대로 TCP 커넥션에서 요청 메세지를 읽고 처리한다.

2.2 성능 관련 중요 요소

다음과 같은 요인과 그로 인한 성능상의 문제를 포함해 영향을 주는 일반적인 TCP 관련 지연들에 대해서 다른다.

  1. TCP 커넥션의 핸드셰이크 설정
  2. TCP 편승(piggyback) 확인 응답(acknowledgment)을 위한 확인 응답 지연 알고리즘
  3. 인터넷의 혼잡을 제어하기 위한 TCP의 느린 시작 slow-start
  4. 데이터를 한데 모아 한 번에 전송하기 위한 네이글(nagle) 알고리즘
  5. TIME_WAIT 지연과 포트 고갈

2.2.1 TCP 핸드셰이크 지연 (3 handshake)

어떤 데이터를 전송하든, 새로운 TCP 커넥션을 열 때면,
TCP 소프트웨어는 커넥션을 맺기 위한 조건을 맞추기 위해 연속으로 IP 패킷을 교환한다.
다음은 TCP 커넥션이 핸드셰이크를 하는 순서다. (예전에 정리한 글)

  1. 클라는 새로운 TCP 커넥션을 생성하기 위해
    작은 TCP 패킷을 서버에게 보낸다.
    • 그 패킷은 SYN(synchronize sequence numbers)라는 특별한 flag를 가진다.
      (TCP flags의 종류)
    • 커넥션 생성 요청이라는 뜻
  2. 서버가 그 커넥션을 받으면 몇 가지 커넥션 매개변수를 산출하고,
    • 커넥션 요청이 받아들여졌음을 의미하는 SYN + ACK(acknowledgment) flag를 포함한 TCP 패킷을 클라에게 보낸다.
  3. 마지막으로 클라는 커넥션이 잘 맺어졌음을 알리기 위해서 서버에게 다시 확인 응답 신호를 보낸다. (ACK)
    • 오늘날 TCP는 클라가 이 확인 응답 패킷과 함께 + 데이터를 보낼 수 있다.
  • 실제 개발자들은 이 패킷들을 보지 못한다.
  • TCP 커넥션이 생성될 때 발생하는 지연이 전부다.
  • 크기가 작은 HTTP 트랜잭션은 50% 이상의 시간을 TCP를 구성하는 데 쓴다.
  • TCP 구성으로 인한 지연을 제거하기 위해서 HTTP가 이미 존재하는 커넥션을 어떻게 재활용하는지 알아보자.

2.2.2 확인 응답 지연 알고리즘

  • 인터넷 자체가 패킷 전송을 완벽히 보장하지는 않기 때문에, TCP는 성공적인 데이터 전송을 보장하기 위해서 자체적인 확인 체계를 가진다.
  • TCP 세그먼트는 순번데이터 무결성 체크섬을 가진다.
  • 송신자의 기준은 먼저 시작한 곳
    • 수신자는 세그먼트를 온전히 받으면, 작은 확인 응답 패킷을 송신자에게 반환한다. (ACK)
    • 송신자가 특정 시간 안에 확인 응답 메세지를 받지 못하면, 패킷이 파기되었거나 오류가 있는 것으로 판단하고 데이터를 다시 전송한다.

데이터 보낼 때 같이 보내면 되겠다!

  • 확인 응답은 그 크기가 작기 때문에 TCP는
    같은 방향으로 송출되는 데이터 패킷에 확인 응답을 편승시킨다. (piggyback)
  • TCP는 송출 데이터 패킷과 확인 응답을 하나로 묶음으로써
    네트워크를 좀 더 효율적으로 사용한다.
  • 확인 응답 지연은 송출할 확인 응답을 특정 시간 동안(0.1초 ~ 0.2초) 버퍼에 저장해 두고,
    확인 응답을 편승시키기 위한 송출 데이터 패킷을 찾는다.

막상 HTTP에서는

  • HTTP 동작 방식은 확인 응답이 송출 데이터 패킷에 편승할 기회를 감소시킨다.
  • 편승할 패킷을 찾으려고 하면, 해당 방향으로 송출될 패킷이 많지 않기 때문에,
    확인 응답 지연으로 인한 지연이 자주 발생한다.

2.2.3 TCP 느린 시작 slow start

TCP 느린 시작

  • TCP 커넥션은 시간이 지나면서 자체적으로 튜닝되어서,
    처음에는 커넥션의 최대 속도를 제한하고,
    데이터가 성공적으로 전송됨에 따라서, 속도 제한을 높여나간다.
  • 인터넷의 갑작스러운 부하와 혼잡을 방지하는 데 쓰인다.

혼잡 윈도를 연다. opening the congestion window

  • TCP 느린 시작은 TCP가 한 번에 전송할 수 있는 패킷의 수를 제한한다.
  • 패킷이 성공적으로 전달되는 각 시점에 송신자는 추가로 2개의 패킷을 더 전송할 수 있는 권한을 얻는다.
  • HTTP 트랜잭션에서 전송할 데이터의 양이 많으면 모든 패킷을 한 번에 전송할 수 없다.
    한 개의 패킷만 전송하고 확인 응답을 기다렸다 받으면, 2개의 패킷을 보낼 수 있고, 그 패킷 각각에 대한 확인 응답을 받으면 총 4개의 패킷을 보낼 수 있게 된다.
  • 혼잡제어 기능 때문에 새로운 커넥션은 튜닝된 커넥션보다 느리다. (지속커넥션과 연관)

2.2.4 네이글 알고리즘과 TCP_NODELAY

  • “가능하면 조금씩 여러 번 보내지 말고 한 번에 많이 보내라(Effective TCP)” 라는 원칙을 기반으로 만들어진 알고리즘이다.
  • John Nagle의 이름을 따서 만들어졌다.
  • 네이글 알고리즘은 HTTP 성능 관련 여러 문제를 발생시킨다.
    1. 크기가 작은 HTTP 메세지는 패킷을 채우지 못해, 앞으로 생길지 생기지 않을지 모르는 추가적인 데이터를 기다리며 지연될 것이다.
    2. 확인 응답 지연과 함께 쓰일 경우 비효율적이다.
    • HTTP 스택에 TCP_NODELAY 파라미터 값을 설정하여 네이글 알고리즘을 비활성화하기도 한다.

그림 출처

TCP_NODELAY 참고글

2.2.5 TIME_WAIT의 누적과 포트 고갈

  • TCP 커넥션의 endpoint에서 TCP 커넥션을 끊으면,
    endpoint에서는 커넥션의 IP 주소와 포트 번호를 메모리의 작은 제어영역에 기록해 놓는다.
  • 이 정보는 같은 주소와 포트 번호를 사용하는
    새로운 TCP 커넥션이 일정 시간 동안에는 생성되지 않게 하기 위한 것이다.
  • 이전 커넥션과 관련된 패킷이
    그 커넥션과 같은 주소와 포트 번호를 가진 새로운 커넥션에 삽입되는 문제를 방지한다.
  • 보통 세그먼트의 최대 생명주기에 두 배 정도 2MSL이라고 불리며 보통 2분 정도

    오래전, 라우터가 매우 느렸던 때에는 중복되는 패킷의 복제본이 삭제되기 전까지 인터넷에 있는 큐에 1분이 넘게 보관되어 있었기 때문에 최대 생명주기를 1분으로 정했다.

  • 현대의 빠른 라우터들 덕분에 커넥션이 닫힌 후에 중복되는 패킷이 생기는 경우는 거의 없어졌다.

Time wait에 대한 글
카카오 블로그
toast 블로그


3. HTTP 커넥션 관리

커넥션을 생성하고 최적화하는 HTTP 기술을 설명할 것이다.

3.1 흔히 잘못 이해하는 Connection 헤더

  • HTTP는 클라와 서버 사이에 중개 서버가 놓이는 것을 허락한다. (프락시, 중개)
  • 어떤 경우에는 두 개의 인접한 HTTP 앱이
    현재 맺고 있는 커넥션에만 적용될 옵션을 지정해야 할 때가 있다.
  • 이때 HTTP Connection 헤더를 사용하면 맺고 있는 커넥션에만 값이 적용 가능하다.
  • Connection 헤더에는 3가지 종류의 토큰이 전달될 수 있다.
  • HTTP/2에서는 무시된다.
  1. HTTP header field name
    헤더 보호하기
    • 이 커넥션에만 해당되는 헤더들을 나열
    • 해당 필드들은 현재 커넥션만을 위한 정보이므로,
      다음 커넥션에 해당 헤더를 전달하면 안된다.
    • Connection 헤더에는 hop-by-hop 헤더 명을 기술한다.
      • hop은 각 서버를 의미하며 hop-by-hop은 특정 두 서버 간에만 영향을 미치고, 다른 서버 간에는 영향을 미치지 않음을 뜻한다.
    • Connection 헤더에 있는 헤더 필드의 이름에 해당되는 헤더들은 모두 삭제되어야 한다.
  2. 임시적인 토큰값: 커넥션에 대한 비표준 옵션을 의미
  3. close: 커넥션이 작업이 완료되면 종료되어야 함을 의미.
  4. keep-alive

mdn

3.2 순차적인 트랜젝션 처리에 의한 지연

  • 커넥션 관리가 제대로 이루어지지 않으면 TCP 성능이 매우 안 좋아질 수 있다.
  • 만약 3개의 이미지가 있는 웹페이지에 접근한다면?
    • 4개의 HTTP 트랜젝션을 만들어야 함. (html+이미지)
    • 만약 각 트랜젝션이 새로운 커넥션을 필요로 한다면?
      • 커넥션을 맺는데 발생하는 지연과 함께 느린 시작 지연이 발생할 것이다.
  • 순차처리로 인한 지연에는 물리적인 지연뿐 아니라,
    하나의 이미지를 내려받고 있는 중에는 웹페이지의 나머지 공간에 아무런 변화가 없어서 느껴지는 심리적인 지연도 있다.

HTTP 커넥션의 성능을 향상시킬 수 있는 여러 최신 기술이 있다.

  1. 병렬 커넥션 parallel
    • 여러 개의 TCP 커넥션을 통한 동시 HTTP 요청
  2. 지속 커넥션 persistent
    • 커넥션을 맺고 끊는 데서 발생하는 지연을 제거하기 위한 TCP 커넥션의 재활용
  3. 파이프라인 커넥션 pipelined
    • 공유 TCP 커넥션을 통한 병렬 HTTP 요청
  4. 다중 커넥션 multiplexed
    • 요청과 응답들에 대한 중재 (실험적인 기술이다..)




참고자료

📚