Skip to content

Latest commit

 

History

History
162 lines (127 loc) · 12.4 KB

File metadata and controls

162 lines (127 loc) · 12.4 KB

커넥션 관리

TCP 커넥션

  • 전 세계 모든 HTTP 통신은 패킷 교환 네트워크 프로토콜의 계층화된 집합인 TCP/IP 를 통해 이루어짐
  • 일단 커넥션이 맺어지면 클라이언트와 서버 컴퓨터 간에 주고받는 메시지들은 손실/손상 없이 안전하게 전달됨

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

  • HTTP 커넥션은 몇몇 사용 규칙을 제외하고는 TCP 커넥션에 불과함
  • TCP 는 HTTP 에게 닛뢰할 만한 통신 방식을 제공

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

  • TCP 는 IP 패킷(혹은 IP 데이터그램)이라고 불리는 작은 조각을 통해 데이터 전송
  • HTTP 는 IP, TCP, HTTP 로 구성된 프로토콜 스택에서 최상위 계층
  • HTTPS 는 HTTP 에 보안 기능을 더한 버전으로, TLS 나 SSL 로 불리기도 하며, HTTP와 TCP 사이에 있는 암호화 계층
  • IP 패킷이 갖고 있는 정보 - IP 패킷 헤더, TCP 세그먼트 헤더, TCP 데이터 조각

TCP 커넥션 유지하기

  • 컴퓨터는 항상 TCP 커넥션을 여러개 가지고, 포트 번호를 통해 여러 개의 커넥션을 유지함
  • TCP 커넥션 식별 - <발신지 IP 주소, 발신지 포트, 수신지 IP 주소, 수신지 포트>

TCP 소켓 프로그래밍

  • 운영체제는 TCP 커넥션의 생성과 관련된 여러 기능을 제공함
  • 소켓 API 는 TCP와 IP의 세부 사항들을 숨기고 주요 인터페이스를 보여줌



TCP의 성능에 대한 고려

  • HTTP 트랜잭션의 성능은 그 아래 계층인 TCP 성능에 영향을 받음

HTTP 트랜잭션 지연

  • 트랜잭션을 처리하는 시간은 TCP 커넥션을 설정하고, 요청을 전송하고, 응답 메시지를 보내는 것에 비해 상당히 짧음
  • 대부분의 HTTP 지연은 TCP 네트워크 지연 때문에 발생함
  • 지연 원인
    1. 클라이언트가 URI 에서 IP 주소와 포트 번호를 알아내는데 시간 소요(요즘은 밀리초 단위에서 끝남)
    2. 클라이언트가 서버로부터 커넥션 허가 응답을 회신하길 기다리는 시간 소요(요즘은 1초 미만)
    3. 요청 메시지가 인터넷을 통해 전달되고 서버에 의해 처리되는데 시간 소요
    4. 웹 서버가 HTTP 응답을 보내는데 시간 소요

TCP 커넥션 핸드셰이크 지연

  • 새로운 TCP 커넥션을 열 때, 커넥션을 맺기 위한 조건을 맞추기 위해 연속으로 IP 패킷을 교환하고, 이는 HTTP 성능 저하로 이어짐
  • 핸드셰이크 순서
    1. 클라이언트 -> 서버: 작은 TCP 패킷 전송(SYN 플래그 가짐)
    2. 서버 -> 클라이언트: 커넥션 매개변수 산출, 요청 승인 플래그(SYN, ACK)를 포함한 TCP 패킷 전송
    3. 클라이언트 -> 서버: 커넥션 잘 맺어졌음을 알리는 응답 신호 보냄

확인 응답 지연

  • 각 TCP 세그먼트는 순번과 데이터 무결성 체크섬을 가짐
  • 각 세그먼트의 수신자는 세그먼트를 온전히 받으면 작은 확인응답 패킷을 송신자에게 반환하고, 송신자가 특정 시간 안에 확인 응답 메시지를 받지 못하면 패킷이 파기되었거나 오류가 있는 것으로 판단하고 데이터 재전송
  • 확인응답은 크기가 작기 때문에 같은 방향으로 송출되는 데이터 패킷에 확인응답을 편승시킴(확인응답을 편승시키기 위한 송출 데이터 패킷을 찾지 못하면 별도 패킷을 만들어 전송)
  • 편승할 패킷을 찾는 알고리즘을 사용하는 과정에서 지연이 자주 발생함

TCP 느린 시작(slow start)

  • TCP 커넥션은 시간이 지나면서 자체적으로 튜닝되기 때문에 데이터의 성공적인 전송에 따라 속도 제한을 늘려감
  • 한 번에 전송할 수 있는 패킷 수를 제한했다가, 성공시 2개의 패킷을 추가 전송할 수 있는 권한을 얻어감(혼잡 윈도를 연다, opening the congestion window)

네이글(Nagle) 알고리즘과 TCP_NODELAY

  • 각 TCP 세그먼트가 플래그와 헤더를 포함해 전송되기 때문에, 많은 수의 패킷을 전송한다면 네트워크 성능이 크게 떨어짐
  • 네이글 알고리즘은 패킷 전송 전, 많은 양의 TCP 데이터를 한개의 덩어리로 합치는 방식으로, 세그먼트가 최대 크기가 되지않으면 전송을 하지 않음. 단, 다른 모든 패킷이 확인응답을 받았을 경우에는 최대 크기보다 작은 패킷의 전송을 허용함
  • 크기가 작은 경우, 패킷을 채우지 못해 지연 시간이 길어지는 경우가 있음. 확인 응답 지연 알고리즘이랑 함께 쓰면 더 형편없어짐
  • TCP_NODELAY 파라미터 값을 설정해 네이글 알고리즘 비활성화 가능

TIME_WAIT 의 누적과 포트 고갈

  • TCP 커넥션을 끊으면, 종단에서 커넥션의 IP 주소와 포트 번호를 메모리의 작은 영역(control block)에 기록해 놓음. 일정 시간 동안 생성되지 않게 하여 중복된 커넥션이 또 생성되는 것을 방지함
  • 서버가 엄청 빠른 속도로 트랜잭션을 처리하지 않는 이상, TIME_WAIT 포트 고갈은 일어나지 않지만, 커넥션을 너무 많이 맺거나 대기 상태로 있는 제어 블록이 너무 많아지는 상황에 주의 해야함.



HTTP 커넥션 관리

흔히 잘못 이해하는 Connection 헤더

  • HTTP는 클라이언트와 서버 사이에 중개 서버가 놓이는 것을 허락함
  • 서버에 전달할 정보와 현재 커넥션만을 위한 정보가 다르므로, Connection 헤더에 홉별 헤더명을 기술해 잘못된 헤더들이 전달되는 것을 방지함

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

  • 커넥션 관리가 제대로 이루어지지 않으면 TCP 성능 저하 발생함
  • HTTP 커넥션 성능 향상을 위한 최신기술 - 병렬 커넥션, 지속 커넥션, 파이프라인 커넥션, 다중 커넥션



병렬 커넥션

  • 여러 개의 커넥션을 맺어 HTTP 트랜잭션을 병렬로 처리할 수 있게 함

병렬 커넥션은 페이지를 더 빠르게 내려받는다

  • 커넥션 지연이 겹쳐짐으로써 총 지연시간이 줄어듦

병렬 커넥션이 항상 더 빠르진 않음

  • 네트워크 대역폭이 좁을 때는 대부분의 시간을 데이터 전송에 사용하기 때문에 성능상의 장점이 거의 사라짐
  • 여러 개의 커넥션은 메모리를 만힝 소모하고, 자체적인 성능 문제를 발생시킴

병렬 커넥션은 더 빠르게 '느껴질 수' 있다

  • 사용자는 객체가 동시에 보이면서 내려받고 있는 상황을 볼 수 있어 더 빠르게 받고 있다고 느낄 수 있음



지속 커넥션

  • 완료된 커넥션을 끊기 전까지 유지함으로써, TCP 의 느린 시작으로 인한 지연을 피하고 커넥션을 맺기 위한 준비작업에 필요한 시간을 절약하는 방법

지속 커넥션 vs 병렬 커넥션

  • 지속 커넥션은 병렬 커넥션과 함께 사용될 때 가장 효과적임
  • 병렬 커넥션에서 발생했던 느린시작, 병렬 켜넥션 수 제한 등 문제들이 지속 커넥션에서는 해결됨

Keep-Alive 커넥션

  • keep-alive 는 사용하지 않기로 결정되어 HTTP/1.1 명세에서 빠졌었음. 하지만 널리 사용되고 있기 때문에 HTTP 애플리케이션은 이를 처리할 수 있게 개발해야 함
  • keep-alive 헤더는 커넥션을 유지하길 바라는 요청일 뿐임. 요청을 받았다고해서 무조건 따를 필요가 없고 언제든 커넥션을 끊거나 처리되는 트랜잭션의 수를 제한할 수 있음
  • HTTP/1.0 에서 기본으로 사용되지 않음
  • 커넥션을 계속 유지하려면 Connection: Keep-Alive 요청 헤더 보내야 함
  • 응답 헤더가 없는 것을 보고 서버가 응답 후 커넥션을 끊을 것임을 알 수 있음
  • 트랜잭션이 끝나는 시점에 기존 메시지의 끝과 새로운 메시지의 시작점을 알 수 없어 정확한 Content-length 값을 보내야 함
  • 프락시와 게이트웨이는 Connection 헤더의 규칙을 철저히 지켜야 함
  • 정석대로라면 Connection 헤더를 인식하지 못하는 프락시 서버와는 맺어져스는 안됨.
  • 응답 전체를 받기 전에 커넥션이 끊겼을 경우, 별다른 문제가 없으면 요청을 다시 보낼 수 있게 준비되어야 함

Proxy-Connection

  • HTTP 최신 버전을 지원하지 않아도 모든 헤더를 무조건 전달하는 문제를 해결할 수 있는 방법
  • Proxy-Connection 이라는 헤더를 사용함으로써 무조건적으로 헤더를 전달하는 멍청한 프락시여도, 웹 서버에서 이를 무시하기 때문에 문제를 발생시키지 않고, 영리한 프락시의 경우 Proxy-Connection 헤더를 Connection 헤더로 바꾸어 원하는 효과를 얻을 수 있음
  • 문제를 발생시키는 프락시들은 보이지 않는 경우가 많으므로 해당 애플리케이션들이 지속 커넥션을 명확하게 구현하는 것은 중요함

HTTP/1.1의 지속 커넥션

  • keep-alive 커넥션을 지원하는 대신, 개선된 설계의 지속 커넥션 지원
  • HTTP/1.1의 지속커넥션은 활성화가 기본값이고 끊기 위해 Connection: close 를 명시해야 함. 단 Connection: close 를 보내지 않는 것이 커넥션을 영원히 유지하겠다는 것을 의미하진 않음

지속 컨게션의 제한과 규칙

  • 클라이언트가 커넥션을 끊겠다고 명시했으면 추가 요청이 불가하고, 추가 요청을 보내지 않을거라면 마지막 요청에 끊겠다는 헤더를 보내야 함
  • 커넥션에 있는모든 메시지가 자신의 길이 정보를 명확하게 가지고 있을 때만 커넥션 지속 가능
  • HTTP/1.1 프락시는 클라이언트와 서버 각각에 대해 별도의 지속 커넥션을 맺고 관리해야 함
  • HTTP/1.1 프락시 서버는 클라이언트의 지원 범위를 모르면 지속 커넥션을 맺으면 안됨
  • HTTP/1.1 기기는 헤더 값과 무관하게 언제든 커넥션을 끊을 수 있음
  • HTTP/1.1 애플리케이션은 중간에 끊어지는 커넥션 복구 가능해야 함
  • 하나의 사용자 클라이언트 당 2개의 지속 커넥션만을 유지해야 함



파이프라인 커넥션

  • HTTP/1.1 은 지속 커넥션을 통해 요청을 파이프라이닝 하는 것이 가능함
  • 지속 커넥션 확인 전까지는 파이프라인을 잇지 말아야 함
  • HTTP 응답은 요청 순소와 같게 와야 함
  • 완료되지 않은 요청이 파이프라인에 있으면 언제든 다시 요청을 보낼 준비가 되어있어야 함
  • POST 요청처럼 반복해서 보냈을 때 문제가 생기는 요청은 파이프라인을 통해 보매면 안됨

커넥션 끊기에 대한 미스테리

  • 커넥션 관리에는 명확한 기준이 없음

'마음대로' 커넥션 끊기

  • 언제든 TCP 전송 커넥션을 끊을 수 있음(에러가 없어도)
  • 보통은 메시지를 다 보낸 다음 끊지만, 이상한 곳에서 끊길 가능성도 있음

Content-Length 와 Truncation

  • Content-Length가 존재하지 않거나 값이 실제 전달된 엔터티의 길이와 다르면 서버에게 정확한 길이 물어봐야 함

커넥션 끊기의 허용, 재시도, 멱등성

  • 트랜잭션 수행 중에 커넥션이 끊긴다면, 해당 트랜잭션을 재시도 했을 때 문제가 없을 경우엔 커넥션을 다시 맺고 재전송을 시도함
  • 트랜잭션이 항상 같은 결과를 반환한다면, 해당 트랜잭션은 멱등하다고 하는데, 멱등하지 않은 요청은 파이프라인을 통해 요청하면 안됨

우아한 커넥션 끊기

  • 전체 끊기와 절반 끊기
    • 애플리케이션은 입력채널과 출력채널 중 하나를 끊거나 둘다 끊을 수 있음
    • 둘다 끊을 땐 close() 호출, 개별 끊기는 shutdown() 호출
  • TCP 끊기와 리셋 에러
    • 보통은 출력 채널을 끊는 것이 안전함(클라이언트에서 더는 데이터를보내지 않을 거라고 확신할 수 없는 이상)
  • 우아하게 커넥션 끊기
    • 애플리케이션 자신의 출력 채널을 먼저 끊고, 다른 쪽 기기의 출력 채널이 끊기기를 기다리는 것
    • 상대가 절반 끊기를 구현했다는 보장도 없고, 검사해준다는 보장도 없어서 끊기 이후에도 주기적인 상태 검사 필요
    • 타임 아웃 내에 입력 채널이 끊기지 않는다면, 리소스 보호를 위해 커넥션을 강제로 끊을 수 있음