티스토리 뷰

Network

TCP 커넥션 관리

realizers 2023. 4. 4. 22:16
728x90
반응형

TCP 커넥션


  • TCP는 3 way hand shake를 통해 연결을 맺고, 4 way hand shake를 통해 연결을 해지합니다.

 

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

 

  • HTTP가 메시지를 전송하고자 할 경우, 현재 연결되어 있는 TCP 커넥션을 통해 데이터의 내용을 순서대로 전송합니다.
  • TCP는 세그먼트라는 단위로 데이터 스트림을 잘게 나누고, 세그먼트를 IP 패킷이라고 불리는 소포에 담아 인터넷을 통해 데이터를 전달합니다. 이러한 TCP 세그먼트는 하나의 IP 주소에서 다른 IP 주소로 IP 패킷에 담아 전달됩니다.
  • IP 패킷 헤더는 발신자와 목적지 IP 주소, 크기, 기타 플래그를 가집니다.
  • TCP 세그먼트 헤더는 TCP 포트 번호, TCP 제어 플래그, 데이터의 순서 등을 가집니다.

세그먼트 전송 과정

 

💡 TCP 커넥션 유지하기

 

  • 컴퓨터는 항상 여러개의 TCP 커넥션을 가지고 있는데, 이러한 여러개의 TCP는 포트 번호를 통해 여러개의 커넥션을 유지합니다.

 

TCP 성능에 대한 고려


  • HTTP는 TCP 바로 위에 존재하는 계층이기 때문에 HTTP 트랜잭션의 성능은 바로 아래에 있는 TCP 성능에 영향을 받습니다.

 

💡 클라이언트와 서버의 연결 과정

 

  • 아래와 같은 과정에서는 하드웨어 성능, 네트워크와 서버의 전송 속도, 요청과 응답 메시지의 크기, 클라이언트와 서버 간의 거리에 따라 크게 달라지게 됩니다.
  1. 클라이언트는 URL에서 서버의 IP 주소와 포트 번호를 알아내야 합니다. 여기서 해당 URL에 접근한 적이 없으면 DNS를 분석하게 됩니다. 분석한 내용을 토대로 URL에 있는 호스트명을 IP 주소로 변환하게 됩니다.
  2. 클라이언트는 TCP 커넥션 요청을 서버에게 보내고 서버가 커넥션을 허용하기까지 기다립니다. 
  3. 커넥션이 맺어지면 클라이언트는 HTTP 요청을 새로 생성된 TCP 파이프를 통해 전송합니다. 서버는 전달받는 데이터를 처리하게 됩니다. 
  4. 서버가 처리가 완료되었으면 HTTP 응답을 보내게 됩니다.

 

💡 성능에 관련된 중요 요소

 

  • TCP 커넥션의 헨드셰이크 설정
  • TCP의 편승, 확인응답(ack)을 위한 확인응답 지연 알고리즘
  • 인터넷의 혼잡을 제어하기 위한 TCP slow start
  • 데이터를 한곳에 모아 한번에 전송하기 위한 네이글 알고리즘

 

    TCP 커넥션의 헨드셰이크 설정

 

  • 아래 과정은 TCP 커넥션이 연결을 맺기 위한 과정입니다.
  • 작은 크기의 데이터 전송에 커넥션이 사용된다면 HTTP 성능을 크게 저하시킬 수 있습니다.

 

    확인 응답 지연

 

  • 인터넷 자체가 패킷 전송을 완벽히 보장하지 않기 때문에 TCP는 성공적인 데이터 전송을 보장하기 위해서 자체적인 확인 체계를 가집니다.
  • 각 TCP 세그먼트는 순번과 데이터 무결성을 위한 체크섬을 가집니다. 각 세그먼트의 수신자는 세그먼트를 온전히 받으면 ACK 패킷을 송신자에게 반환합니다. 만약 송신자가 특정 시간에 ACK 패킷을 받지 못하면 패킷이 파기되었거나 오류가 있는 것으로 판단하고 데이터를 다시 전송합니다.
  • ACK 패킷은 크기가 작기 때문에 TCP는 같은 방향으로 송출되는 데이터 패킷에 ACK 패킷을 편승시킵니다. 이렇게 TCP는 송출 데이터에 ACK 패킷을 묶음으로써 네트워크를 조금 더 효율적으로 사용합니다.
  • ACK 패킷이 같은 방향으로 가는 데이터 패킷에 편승되는 경우를 늘리기 위해 많은 TCP는 '확인 응답 지연 알고리즘'을 구현하는데, 이는 ACK 패킷을 특정 시간동안 버퍼에 저장해두고, ACK 패킷을 편승시키기 위한 송출 데이터를 찾습니다. 만약 일정시간 동안 송출 데이터를 찾지 못하면 ACK 패킷은 별도의 패킷을 만들어 전송합니다.

 

    TCP 느린 시간(slow start)

 

  • TCP의 데이터 전송 속도는 TCP 커넥션이 만들어진지 얼마나 지났는가에 따라 달라질 수 있습니다. TCP 커넥션은 시간이 지나면서 자체적으로 튜닝되어 처음에는 커넥션의 최대 속도를 제한하고, 데이터가 성공적으로 전송됨에 따라 속도 제한을 높여나갑니다. 이렇게 조율하는 것을 TCP slow start라 부르며, 이것은 인터넷이 갑작스러운 부하의 혼잡을 방지하는데 사용됩니다.
  • TCP slow start는 TCP가 한번에 전송할 수 있는 패킷을 수를 제한합니다. 예를들어 패킷이 성공적으로 전달되는 각 시점에 송신자는 추가적으로 2개의 패킷을 더 전송할 수 있는 권한을 얻습니다. HTTP 트랜잭션에서 전송할 데이터의 양이 많으면 모든 패킷을 한번에 전송할 수 없습니다. 대신 한 개의 패킷만 전송하고 ACK를 받으면 2개의 패킷을 보낼 수 있으며, 그 패킷은 각각 ACK 패킷을 받아 총 4개의 패킷을 보낼 수 있게 됩니다. 이를 opening the congestion window라 합니다.

 

    네이글 알고리즘

 

  • TCP가 작은 크기의 데이터를 계속 전달한다면 네트워크 성능은 크게 저하될 것입니다. 이를 방지하기 위해 나온게 네이글 알고리즘입니다. 네이글 알고리즘은 네트워크 효율을 위해 패킷을 전송하기 전 많은 양의 TCP 데이터를 한 개의 덩어리로 합치게 됩니다.
  • 네이글 알고리즘은 세그먼트가 최대 크기가 되지 않으면 전송을 하지 않습니다. 
  • 네이글 알고리즘은 여러 문제를 발생시킬 수 있는데, 크기가 작은 HTTP 메시지는 패킷을 채우지 못하기 때문에, 앞으로 생길지 생기지 않을지 모르는 추가적인 데이터를 기다리며 지연되게 됩니다.

 

병렬 커넥션


  • 클라이언트가 여러 개의 커넥션을 맺어 여러 개의 HTTP 트랜잭션을 병렬로 처리합니다.

 

    장점

 

  • 각 Connection의 지연시간을 겹치게 하면 총 지연시간을 줄일 수 있습니다.
  • 클라이언트의 인터넷 대역폭을 하나의 Connection이 다 써버리는 것이 아니라면 나머지 객체를 내려받는데 남은 대역폭을 사용할 수 있습니다.

    단점

 

  • 각 트랜잭션마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소요됩니다.
  • 각 새로운 커넥션은 TCP slow start로 인해 성능이 저하됩니다.
  • 다수의 Connection은 메모리를 많이 소모하고 자체적인 성능 문제를 발생시킵니다.
  • 예를들어 백명의 사용자가 100개의 커넥션을 맺고 있다면 서버는 총 10,000개의 커넥션을 맺게되는데 이는 서버에 과부화를 주기 때문에 서버는 특정 클라이언트로부터 과도한 수의 커넥션이 맺어졌을 때 임의로 끊어버릴 수 있습니다.

 

지속 커넥션


  • HTTP/1.1을 지원하는 기기는 처리가 완료된 후에도 TCP Connection을 유지하여 앞으로 있을 HTTP 요청에 재사용할 수 있습니다.
  • 처리가 완료된 후에도 계속 연결된 상태로 있는 TCP Connection을 지속 커넥션이라 부릅니다.
  • 비지속 커넥션은 각 처리가 끝날 때마다 커넥션을 끊지만, 지속 커넥션은 클라이언트나 서버가 커넥션을 끊기 전까지 커넥션을 유지합니다.
  • 지속 커넥션을 재사용함으로써, 커넥션을 맺기 위한 준비작업의 시간을 절약할 수 있고, TCP slow start로 인한 지연을 피함으로써 데이터를 더 빠르게 전송할 수 있습니다.

 

    장점

 

  • 새로운 커넥션을 맺기 위한 사전 작업과 지연을 줄여주고, 튜닝된 커넥션을 유지하면서 커넥션의 수를 줄여줍니다.

    단점

 

  • 지속 커넥션을 잘못 관리하는 경우 계속 연결된 상태로 있는 수많은 커넥션이 쌓이게 됩니다.

 

💡 Keep-Alive 

 

  • Keep-Alive 헤더는 커넥션을 유지하길 바라는 요청일 뿐이므로, 클라이언트나 서버는 Keep-Alive 요청을 받았다고 해서 무조건 따를 필요가 없습니다.
  • HTTP/1.0에서 기본적으로 사용되지 않으며, 클라이언트는 요청 헤더에 Connection: Keep-Alive를 선언해야 합니다.
  • 지속 커넥션을 계속 유지하기 위해서는 모든 메시지의 헤더에 Connection: Keep-Alive를 포함해야하며, 만약 클라이언트나 서버의 헤더에 해당 문구가 없으면 커넥션이 끊어집니다.
  • 프락시와 게이트웨이는 Connection 헤더의 규칙을 철저히 지켜야 하는데, 프락시와 게이트웨이는 메시지를 전달하거나 캐시에 넣기전 Connection 헤더를 제거해야 합니다.

 

💡 Keep-Alive와 멍청한 프록시

 

  • 프록시는 Connection 헤더를 이해하지 못하기 때문에 해당 헤더를 삭제하지 않고, 요청 그대로 프록시에게 전달하면 문제가 발생할 수 있습니다.

 

    문제발생 과정

 

  1. 클라이언트는 프록시에게 Connection: Keep-Alive 헤더와 함께 메시지를 보냅니다.
  2. 멍청한 프록시는 Connection: Keep-Alive를 이해하지 못하고 그대로 서버로 보냅니다.
  3. 서버는 멍청한 프록시로부터 Connection: Keep-Alive 헤더를 전달받아 프록시가 지속 커넥션을 유지하길 바라고 있다고 착각하게 됩니다. 하지만 멍청한 프록시는 Connection: Keep-Alive를 이해하지 못하고 있습니다.
  4. 멍청한 프록시는 서버로부터 받은 Connection: Keep-Alive 헤더를 포함하여 응답 메시지를 클라이언트에게 전달합니다.
  5. 전달받은 클라이언트는 이제 서버와 지속 커넥션을 유지하고 있다 생각하지만 멍청한 프록시는 Connection: Keep-Alive를 이해하지 못했습니다.
  6. 프록시는 이제 자신의 역할이 끝났다고 생각하고, 커넥션을 끊기 기다립니다. 하지만 클라이언트나 서버는 착각중이므로 커넥션을 종료하지 않습니다.
  7. 이때 클라이언트가 다음 요청을 보내게된다면, 커넥션이 유지되고 있는 프록시에 그 요청을 보내게 되는데, 프록시는 같은 커넥션상에 다른 요청이 오는 경우는 예상하지 못하기 때문에 해당 요청은 무시되게 브라우저는 아무런 응답없이 기다리게 됩니다. 이러한 잘못된 통신으로 인해 브라우저는 자신이나 서버가 타임아웃이 날때까지 기다립니다.

💡 Proxy-Connection

 

  • 멍청한 프록시를 해결하기 위해 Proxy-Connection 헤더를 사용할 수 있는데 모든 상황에서 동작하지는 않습니다.
  • Proxy-Connection은 프록시를 별도로 설정할 수 있는 현대의 브라우저들에서 지원하고 있으며, 많은 프록시들도 인식합니다.
  • 지속 커넥션 헨드셰이킹을 이해할 수 있는 프록시라면 의미없는 Proxy-Connection 헤더를 Connection 헤더로 바꿉니다. 프록시에 Proxy-Connection 헤더를 보내더라도 클라이언트와 프록시 사이 혹은 서버와 프록시 사이에 Keep-Alive 커넥션이 맺어지지 않습니다.
  • 똑똑한 프록시는 Proxy-Connection 헤더가 Keep-Alive를 요청하는 것임을 인식하여, Keep-Alive 커넥션을 맺기 위해 자체적으로 서버에 전달합니다.
  • 하지만 중간에 멍청한 프록시가 있다면 이 또한 멍청해집니다.

 

 

 

 

 

 

 

 

728x90
반응형

'Network' 카테고리의 다른 글

HTTP 메시지  (0) 2023.03.26
URL과 리소스  (0) 2023.03.18
HTTP에 대해  (0) 2023.03.18
Network - TCP-UDP란(feat. 3 way hand shake, 4 way hand shake)  (2) 2022.01.04
Network - HTTP 메서드와 안정성, 캐시가능성 그리고 멱등성  (0) 2022.01.01