커넥션 관리

dragonappear·2023년 3월 9일
0

HTTP 완벽 가이드

목록 보기
3/3


TCP 성능이 HTTP 트랜잭션 속도를 좌지우지 한다.

대부분의 HTTP 네트워크 지연은 TCP 네트워크 지연 때문에 발생한다.

TCP 3-way handshake

확인응답 지연

  • TCP는 같은 방향으로 송출되는 데이터 패킷에 확인응답을 편승시킨다.

  • TCP는 송출 데이터 패킷과 확인응답을 하나로 묶음으로써 네트워크를 좀 더 효율적으로 사용한다

  • 확인응답 지연은 송출할 확인응답을 특정 시간 동안 버퍼에 저장해두고, 확인응답을 편승시키기 위한 송출 데이터 패킷을 찾는다

    • 일정 시간 동안 송출 패킷을 찾지 못하면 확인 응답은 별도의 패킷을 만들어 전송된다.
  • 요청/응답 두가지 형식으로만 동작하는 HTTP는 송출 데이터 패킷에 확인 응답을 편승할 기회를 감소시킨다

    • 해당 방향으로 송출될 패킷이 적기 때문이다.

slow start

  • 네트워크 혼잡 제어를 위해 TCP는 Congestion Window Size를 제어하면서 전송한다.

  • 처음부터 데이터를 무작정 많이 보내지 않는다.

  • 이 혼잡제어 기능 때문에, 새로운 커넥션은 이미 어느정도 데이터를 주고받은 튜닝된 커넥션보다 느리다.

  • 튜닝된 커넥션이 더 빠르기 때문에, HTTP는 이미 존재하는 커넥션을 재사용하는 기능이 있다.

nagle 알고리즘

  • 네트워크 효율을 위해서, 패킷을 전송하기 전에 많은 양의 TCP 데이터를 한 개의 데이터로 합쳐 전송한다.
  • 송신 버퍼에서 데이터를 저장했다가, 확인 응답이 오면 TCP 패킷을 전송한다.
    • 상대방이 확인응답 지연을 사용하고, 내가 네이글 알고리즘을 사용한다고 가정하면, 효율이 엄청 떨어진다.

HTTP 커넥션 맺기

HTTP 트랜잭션을 처리하기 위해 TCP 커넥션을 맺고 끊고, 맺고 끊고하는 과정은 비효율적이다.
HTTP 성능을 향상시키기 위한 커넥션 관리를 아래에서 알아보자

Connection 헤더에 대한 오해

Connection 헤더는 홉별(hop by bop)헤더이다. 오직 한 개의 전송 링크에만 적용되며, 다음 서버로는 전달되어서는 안됨.

  • HTTP 메시지는 클라이언트에서 서버까지 중개 서버들을 하나씩 거치면서 전달된다.

  • 두 개의 인접한 HTTP 어플리케이션이 현재 맺고 있는 커넥션에만 적용될 옵션을 지정해야 할 때가 있다. 그 값들은 다른 커넥션에 전달되지 않아야 한다.

    • 예를 들어, 다음 메시지를 보낸 다음 끊어져야 할 커넥션은 Connection:close라고 명시할 수 있다.
  • Connection 헤더에는 세가지 종류의 토큰이 전달될 수 있다.

    • HTTP 헤더 필드 명: 이 커넥션에만 해당되는 헤더들을 나열
    • 임시적인 토큰 값: 커넥션에 대한 비표준 옵션을 의미
    • close: 커넥션이 작업이 완료되면 종료되어야 함을 의미
  • HTTP 애플리케이션은 Connection 헤더와 함께 메시지를 전달받으면, 수신자는 송신자에게서 온 요청에 기술되어있는 모든 옵션을 적용

  • 그리고 다음 홉에 메시지를 전달하기 전에 Connection 헤더와 헤더에 기술되어 있던 모든 헤더를 삭제한다.


병렬 커넥션

여러개의 TCP 커넥션을 통한 동시 HTTP 요청하는 방식이다

일반적으로 병렬적으로 처리하는 것이 좋긴하지만, 항상 더 빠른것은 아니다.

  • 클라이언트 대역폭이 좁을 때 대부분의 시간을 데이터를 전송하는데만 사용할 수 있다.

  • 또한 다수의 커넥션은 메모리를 많이 소모하고 자체적인 성능 문제를 발생한다.

  • 뿐만 아니라, 서버는 다른 여러 사용자의 요청도 함께 처리해야 하기 때문에 일반적으로 수백개의 커넥션을 허용하지 않는다.

  • 브라우저는 실제로 병렬 커넥션을 사용하지만 적은 수(최신 브라우저의 경우 6~8)의 병렬 커넥션만을 허용한다.

  • 서버는 특정 클라이언트로부터 과도한 수의 커넥션이 맺어졌을 경우, 그것을 임의로 끊어버릴 수 있다.

단점

  • 요청할때마다 TCP 연결을 새로 맺어야 한다.
  • TCP 연결을 새로하기 때문에, 느린 시작을 한다.
  • 실제로 연결할 수 있는 병렬 커넥션의 수에는 제한이 있다.

TCP Syn Flooding


지속 커넥션

커넥션을 맺고 끊는 데서 발생하는 지연을 제거하기 위한 TCP 커넥션 재활용하는 방식이다.

  • 비지속 커넥션은 각 처리가 끝날때마다 커넥션을 끊지만,
  • 지속 커넥션은 클라이언트나 서버가 커넥션을 끊기 전까지는 커넥션을 유지한다.
  • 커넥션을 재사용함으로써, TCP 연결 및 튜닝된 커넥션을 사용함으로써 더 빠르게 데이터를 전송할 수 있다.

위의 장점을 가지고 있지만, 지속 커넥션을 잘못 관리할 경우, 계속 연결된 상태로 수많은 커넥션이 쌓이게 될 수 있다.
이는 클라이언트와 서버의 불필요한 리소스 낭비를 유발한다.

지속 커넥션 + 병렬 커넥션을 함께 사용할 때 가장 효과적이다.
오늘날 많은 웹 어플리케이션은 적은 수의 병렬 커넥션만을 맺고 그것을 유지한다.

두가지 지속 커넥션 타입이 있다.

  • HTTP/1.0+ 에 keep-alive 커넥션
  • HTTP/1.1 에 지속 커넥션

HTTP/1.0 - Keep-Alive 커넥션

  • keep-alive 커넥션은 설계에 문제가 있음에도, 아직까지 많이 이 초기 커넥션을 사용한다.
  • HTTP/1.1에서 설계상의 문제가 수정되었다.

keep-alive 커넥션을 구현한 클라이언트는 커넥션을 유지하기 위해서 Connection:Keep-Alive 헤더를 포함시킨다.
이 요청을 받은 서버는 그 다음 요청도 이 커넥션을 통해 받고자 한다면, 응답 메시지에 같은 헤더를 포함시켜 응답한다.
헤더가 없다면, 클라이언트는 서버가 keep-alive를 지원하지 않으며, 응답 메시지가 전송되고 나면 서버 커넥션을 끊을 것이락 추정한다.

요약하면, keep-alive 헤더는 커넥션을 유지하기를 바라는 요청일 뿐이다. 클라이언트나 서버는 커넥션 헤더를 받았다고 해서 그것을 따를 필요는 없다.또한, 언제든지 커넥션을 끊을 수 있다.

프록시와 게이트웨이는 메시지를 전달하거나 캐시에 넣기 전에 Connection 헤더에 명시된 모든 헤더 필드와 Connection 헤더를 제거해야 한다.

문제점

  • 멍청한 프록시에서 kee-alive 문제가 발생한다.
  • Connection 헤더의 무조건 전달
    • 프록시는 Connection 헤더를 이해하지 못해서 해당 헤더들을 삭제하지 않고 요청 그대로 다음 프록시에 전달한다.
    • 오래되고 단순한 수많은 프록시들이 Connection 헤더에 대한 처리 없이 요청을 그대로 전달한다.

해결

  • 멍청한 프록시에서 발생하는 문제를 해결하기 위해서 브라우저에서는 일반적으로 전달하는 Connection 헤더 대신 비표준인 Proxy-Connection 확장 헤더를 프록시에게 전달한다.
  • 프록시가 Proxy-Connection 확장 헤더를 전달하더라도 웹 서버는 그것을 무시하기 때문에 별 문제가 되지 않는다.

HTTP/1.1 커넥션

  • HTTP/1.1에서는 keep-alive 커넥션 명세가 빠졌다. 그 대신 설계가 더 개선된 지속 커넥션을 지원한다.
  • HTTP/1.0의 keep-alive 커넥션과 달리 HTTP/1.1의 지속 커넥션은 기본으로 활성화되어 있다.
    • 별도로 설정을 하지 않는 한, 모든 커넥션은 지속 커넥션으로 취급한다.
    • 지속 커넥션을 끊으려면 Connection:close 헤더를 명시하면 된다.

파이프라인 커넥션

  • HTTP/1.1은 지속 커넥션을 통해서 요청을 파이프라이닝할 수 있다.
  • 제약사항
    • HTTP 클라이언트는 커넥션이 지속 커넥션인지 확인하기 전까지는 파이프라인을 이어서는 안된다

HTTP 커넥션 끊기

마음대로 커넥션 끊기

  • 클라이언트,서버,캐시,프록시는 언제든지 커넥션을 끊을 수 있다.
  • 보통 커넥션은 메시지를 다 보낸 다음 끊지만, 에러가 있는 상황에서는 중간에서 끊길 수 있다.
  • 지속 커넥션이 일정시간동안 유휴상태에 있으면 서버는 그 커넥션을 끊을 수 있다.
    • 하지만, 클라이언트가 요청을 하는 도중이라고 확신하지는 못한다.
    • 클라이언트가 요청하는 도중 커넥션을 끊으면, 클라이언트는 멱등성 요청, 비멱등성 요청으로 구분하여 재요청을 하거나 이전 요청에 대한 응답을 받을때까지 기다려야 한다.

우아하게 커넥션 끊기

  • TCP 커넥션은 양방향이다.

    • 커넥션의 양쪽에는 입력큐,출력큐가 있다.
  • 전체 끊기 , 절반 끊기

    • 전체 끊기의 경우 입력 채널과 출력채널을 모두 끊는 방식이고, 절반 끊기는 입력채널 혹은 출력채널 중 하나를 개별적으로 끊는다.
    • 보통은 커넥션의 자신의 출력 채널을 끊는 것이 안전하고 예상치 못한 에러를 예방한다.
      • 모든 데이터를 버퍼에서 읽고 나서 데이터 전송이 끝남과 동시에 상대방은 내가 커넥션을 끊었다는 것을 알수 있다.
    • 입력 채널을 끊었는데, 상대방이 데이터를 입력 채널로 전송하면, 운영체제는 TCP'connection reset by peer' 메시지를 상대방에게 보내고, OS는 이것을 심각한 에러로 취급하여 버퍼에 저장된, 아직 읽히지 않은 데이터를 모두 삭제한다.

0개의 댓글