티스토리 뷰

CS

[Network] HTTP/2

신잼 2022. 1. 10. 17:59

HTTP/1.x

문제점

  • Head-Of-Line Blocking
    • 모든 요청이 FIFO로 처리되기 때문에 요청이 blocking 되는 문제
  • RTT(Round Trip Time) 증가
    • 매번 connection 별로 3-way-handshake로 인한 네티워크 지연 초래
  • 무거운 Header
    • 매요청 마다 중복되는 헤더 정보 전송로 인한 header 크기 증가
    • 메타데이터는 항상 일반 텍스트로 전송되고, 전송당 500~800바이트의 오버헤드가 추가
    • HTTP 쿠키를 사용할 경우 수 KB가 추가되기도 함

해결 시도

  1. Image Spriting
    • 여러 이미지를 하나의 이미지로 만들어 사용하는 방법
    • 네트워크 통신은 줄지만 이미지 크기가 커지는 문제
  2. Domain Sharding
    • 도메인 별로 connection을 생성해서 병렬로 요청
    • 브라우저 별로 도메인당 connection 개수 제한 존재
  3. Minified
    • CSS, JS등 코드 공백 등을 없애 데이터 용량을 줄이는 방법
  4. Load Faster
    • HTML 변경으로 해결해보려는 방법
    • 스크립트 위치 변경 등
    • async 및 defer 사용
  5. Data URI Scheme
    • 문서 내 이미지를 Base64 인코딩 된 데이터로 직접 사용하는 방법
  6. 구글의 SPDY
    • HTTP/2의 참고 규격

HTTP/2

  • 어플리케이션 내에서 처리하던 HTTP/1.1 문제를 전송계층 내에서 해결할 수 있도록 한다.
    • 애플리케이션을 더 빠르고, 단순하며 강력하게 만들어준다.
    • 애플리케이션을 최적화하고 성능 개선할 수 있는 새로운 기회를 다양하게 제공한다.
  • 이전의 HTTP 표준을 대체하는 것이 아니라 확장
    • 클라이언트 서버간 데이터 서식(프레임)이 지정되는 방식과 데이터 전송 방식을 수정
    • HTTP 핵심 개념 유지

목표

  • 지연 시간을 줄이기
  • 응답 다중화 지원
  • TTP 헤더 필드의 효율적 압축을 통해 프로토콜 오버헤드를 최소화
  • 요청 우선순위 지정
  • 서버 푸시를 지원

방법

  • 헤더 필드 압축
  • 동일한 연결에서 다중 동시 교환 허용(동일한 연결에서 요청 및 응답 메시지의 인터리빙을 허용)
  • 요청의 우선순위 지정을 허용함으로써 더 중요한 요청이 더 빨리 완료되도록 개선
  • 바이너리 메시지 프레이밍을 사용하여 보다 효율적인 메시지 처리

 

바이너리 프레이밍 계층

 

HTTP 메시지가 캡슐화되어 클라이언트와 서버 사이에 전송되는 방식을 규정한다.

 

 

더 작은 메시지와 프레임으로 분할

바이너리 형식으로 인코딩

장점

  • HOL(Head-of-Line) Block 해결
  • 하나의 연결로 병렬 request, response 가능

 

 

 

 

developers.google.com/web/fundamentals/performance/http2?hl=ko

 

스트림[각주:1], 메시지[각주:2] 및 프레임[각주:3]

HTTP/2 통신은 바이너리로 인코딩 된 프레임의 세분화된 교환이다.

프레임은 특정 스트림에 속한 메시지에 매핑

모든 프레임은 단일 TCP 연결 내에서 다중화

  • 모든 통신은 단일 TCP 연결을 통해 수행
  • 스트림의 수는 제한이 없다
  • 각 스트림에는 메시지 전달에 사용되는 고유 식별자와 우선순위 정보(optional)가 있다.
  • 각 메시지는 하나의 논리적 HTTP 메시지(예: 요청 또는 응답), 하나 이상의 프레임으로 구성
  • 프레임은 통신의 최소 단위
    • 특정 유형의 데이터(예: HTTP 헤더, 메시지 페이로드 등)를 전달

developers.google.com/web/fundamentals/performance/http2?hl=ko

 

요청 및 응답 다중화(Request and Response multiflexing)

HTTP 메시지를 독립된 프레임으로 세분화하고, 이 프레임을 인터리빙

다른 쪽에서 인터리빙 된 프레임의 헤더에 삽입된 스트림 식별자를 통해 이 프레임을 다시 조립

하나의 연결에서 여러 스트림을 캡쳐한 이미지. 스트림 1,3,5 세개 병렬로 존재

스트림 우선순위 지정

각 스트림이 가중치와 종속성을 갖도록 허용

  • 각 스트림에는 1~256 사이의 정수 가중치
  • 각 스트림에는 다른 스트림에 대한 명시적 종속성이 부여 가능

하지만

  • 특정한 처리나 전송 순서를 보장하지 않는다
    • 스트림의 종속성과 가중치는 전송 기본 설정을 표현하는 것이지 요구사항을 표현하는 것이 아니기 때문
  •  클라이언트는 스트림 우선순위 지정을 사용하여 특정 순서로 스트림을 처리하도록 강제할 수 없다

  1. A와 B는 12:4 즉 3:1의 비율로 리소스를 갖는다
  2. 가중치보다 종속성이 우선되기 때문에 D가 C보다 리소스를 먼저 받는다
  3. D다음으로 C 및 E가 리소스를 받고 A와 B는 C가 받는 리소스를 3:1로 갖는다

One connection per origin

하나의 origin에 단일 연결을 사용한다.

  • 동일한 연결을 재사용하여 각 TCP 연결을 더 효율적으로 사용
  • 전반적인 프로토콜 오버헤드를 대폭 감소
  • 클라이언트, 중개 장치 및 원본 서버 등에서 메모리와 처리량 감소

연결 수가 적다는 것은 HTTPS 배포 성능을 개선한다는 점에서 의미가 크다.

  • 값 비싼 TLS Handshake 감소
  • 세션 재사용 향상
  • 필요한 클라이언트 및 서버 리소스 감소

Diagrammatic representation of the SSL Handshake from  msdn.microsoft.com  

흐름 제어

  • TCP의 흐름 제어와 거의 동일한 문제
  • HTTP/2는 TCP 내에서 다중화되기 때문에 TCP의 흐름 제어가 정교하지 않아 개별 스트림 전달을 제어하는데 필요한 애플리케이션 수준의 API를 제공 어려움
  • HTTP/2는 단순한 빌딩 블록 세트를 제공하며, 이를 통해 클라이언트와 서버가 스트림 수준과 연결 수준에서 흐름 제어를 구현
  • 흐름 제어는 종단 간(End-to-End) 방식이 아니라 홉(Hop-by-Hop) 방식

서버 푸시

원래 요청에 응답할 뿐만 아니라 클라이언트가 명시적으로 요청하지 않아도 서버가 추가적인 리소스를 클라이언트에 푸시 가능

HTTP/2는 엄격한 request-response 의미 체계를 탈피하여 일대다의 서버 푸시 워크플로를 지원

  • 서버는 브라우저가 필요한 리소스를 알기 때문에 브라우저가 리소스를 요청하지 않아도 리소스를 전달해서 지연 시간을 더 줄일 수 있다.
  • 아래와 같은 리소스 인라인처럼 client의 요청을 기다리지 않고 수동으로 문서에 인라인 처리 해당 리소스를 클라이언트에 푸시
    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAA
              AAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw=="
         alt="1x1 transparent (GIF) pixel" />​
     
  • 리소스 인라인과 차별되는 이점은 아래와 같다.
    • 클라이언트에 의해 캐시 됨
    • 다른 페이지에서 재사용
    • 다른 리소스와 함께 다중화
    • 서버에서 우선순위 지정
    • 클라이언트에 의한 거부
  • HTTP/2에서는 클라이언트가 서버 푸시의 사용 방식을 완벽하게 제어(연결 시작 시에 SETTINGS 프레임을 통해 전달되며 언제든지 업데이트 가능)
    • 동시에 푸시되는 스트림의 수를 제한
    • 스트림이 최초로 열릴 때 푸시되는 데이터의 크기를 제어하는 초기 흐름 제어 창을 조정
    • 서버 푸시를 완전히 비활성화
  • 푸시된 각 리소스는 인라인 처리된 리소스와는 다른 스트림
    • 클라이언트에 의해 개별적으로 다중화, 우선순위 지정 및 처리가 가능
  • 라우저에 의해 시행되는 유일한 보안 제한은 푸시된 리소스가 동일 출처 정책을 준수해야 한다는 것

PUSH_PROMISE

  • 모든 서버 푸시 스트림은 PUSH_PROMISE 프레임을 통해 시작
  • 푸시된 리소스를 요청하는 응답 데이터보다 먼저 전달되어야 한다
    • 리소스에 대해 중복 요청이 생성되는 것을 막기 위해 클라이언트는 서버가 어떤 리소스를 푸시할지를 알아야 한다
    • HTTP 헤더만 포함된 모든 PUSH_PROMISE 프레임을 상위 요소의 응답(즉, DATA 프레임)보다 먼저 전송
  • 클라이언트가 PUSH_PROMISE 프레임을 수신한 후에 (RST_STREAM 프레임을 통해) 해당 스트림을 거부 가능
    • 예를 들어 이미 해당 리소스가 캐시에 있을 경우
    • HTTP/1.x에서 쓰는 인라인 리소스는 강제 푸시와 동일
  • 클라이언트는 인라인 처리된 리소스를 개별적으로 옵트 아웃하거나 취소하거나 처리 불가능

헤더 압축

 HTTP/2는 오버헤드를 줄이고 성능을 개선하기 위해 헤더 정보를 압축하기 위해 Header Table과 Huffman Encoding 기법을 사용하여 처리하는데 이를 HPACK 압축방식이라 부르며 별도의 명세서(RFC 7541)로 관리

  1. 헤더 필드를 Huffman 코드로 인코딩 -> 필드의 개별 전송 크기 감소
  2. 이전에 표시된 헤더 필드의 색인 목록을 클라이언트와 서버가 유지하고 업데이트(establishes a shared compression context)
    • 이 목록을 참조로 사용하여 이전에 전송된 값을 효율적으로 인코딩

HPACK 압축 콘텍스트는 정적 및 동적 테이블로 구성

  • 정적 테이블: 모든 연결에 사용될 가능성이 있는 공용 HTTP 헤더 필드를 제공(e.g., valid header names)
  • 동적 테이블: 처음에는 비어있으며, 특정 연결에서 교환되는 값에 따라 업데이트

 아직까지 나타나지 않은 값에 대해 정적 Huffman 코딩을 사용하고 또한 정적 테이블이나 동적 테이블에 이미 있는 값을 인덱스로 대체

 

HTTP/2의 request 및 response header가 HTTP/1.x 과 다른 점이 있다.(나머지는 다 같다)

  • 모든 헤더 필드가 소문자 
  • request가 :method, :scheme, :authority, :path의 pesudo 필드로 나뉜다.

 


Reference

 

  1. 구성된 연결 내에서 전달되는 바이트의 양방향 흐름이며, 하나 이상의 메시지가 전달될 수 있습니다. [본문으로]
  2. 논리적 요청 또는 응답 메시지에 매핑되는 프레임의 전체 시퀀스입니다. [본문으로]
  3. HTTP/2에서 통신의 최소 단위이며 각 최소 단위에는 하나의 프레임 헤더가 포함됩니다. 이 프레임 헤더는 최소한으로 프레임이 속하는 스트림을 식별합니다. [본문으로]
반응형

'CS' 카테고리의 다른 글

헷갈리는 network 개념 요약  (0) 2022.02.28
[Network] HTTP/3 and QUIC  (0) 2022.01.18
[Network] HTTP/0.9 ~ 1.1  (0) 2022.01.03
[Network/OS] Network Socket(IP Socket, WebSocket)  (0) 2021.12.27
Interpreter VS Compiler  (0) 2021.11.26
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함