[grpc] 2. grpc의 기반기술 - HTTP/2.0
목차
1. https://dlwnsdud205.tistory.com/326 [grpc] 1. grpc의 기반기술 - RPC
2. https://dlwnsdud205.tistory.com/327 [grpc] 2. grpc의 기반기술 - HTTP/2.0
3. https://dlwnsdud205.tistory.com/328 [grpc] 3. grpc의 기반기술 - Protocol Buffers와 성능 테스트
4. https://dlwnsdud205.tistory.com/329 [grpc] 4. grpc - Java
grpc를 공부하기위해선 우선 grpc의 몇가지 기반 기술들을 알아야한다.
이번 포스팅에서는 HTTP/2.0의 특징등에 대해서 알아볼 것이다.
1. HTTP/1.0 과 HTTP/1.1의 문제점
HTTP/1.0은 TCP커넥션당 한번의 요청과 응답만이 가능했다. 이는 여러번의 TCP connection을 유발했는데, 이 과정에서 3-way-handshaking이 불필요하게 발생되었다. 이 를 막고자 HTTP/1.1은 연결을 끊지않는 keep-alive와 pipelining기법을 적용했다.. 하지만, 파이프라인 은 HOL(Head-Of-Line blocking) 이라는 결함이 존재했는데(HOL은 이전 패킷에 의해 다음 패킷들의 처리가 보류되는 상황을 말한다.), 결과적으로 클라이언트는 요청의 지연시간을 줄이기위해서 다수의 커넥션을 맺고 여러번 요청을 보내야 했다. 게다가 HTTP header는 반복적인 내용이 전달되고, 거대하며 이는 네트워크 트래픽을 불 필요하게 증가시키고 지연시간의 증가로 이어졌다.
2. HTTP/2.0 - Overview
HTTP/2.0은 위와같은 지연시간의 증가와 거대한헤더를 줄이는데에 초점을 맞추고 등장한 기술이다. HTTP/2.0의 특징을 간략히 설명해 보자면,
1. HTTP/2.0은 지연시간은 줄이면서 HTTP/1.1의 핵심기능을 모두 지원한다. 예를들어 HEADERS frame과 DATA frame은
HTTP /1.1 프로토콜에 기초되어 설계되었고 frame의 명칭처럼, HEADERS frame은 HTTP/1.1 프로토콜의 헤더가 들어가며, DATA frame은 페이로드에 해당된다.
2. HTTP/2.0은 스트림을 통한 다중 통신을 지원한다.
3. HTTP/2.0은 클라이언트의 요청이 없어도 서버에서 클라이언트로 메시지를 push할 수 있다.
4. HTTP/2.0은 메시지를 프레임 단위로 끊어서 스트림을 통해 보내는데, 이때, 이진 압축 방식을 통해 frame을 만들어서 네트워크 트래픽을 효율적으로 사용한다.
5. HTTP/2.0은 HTTP/1.1과 마찬가지로 http, https URI schemes를 사용하며, 포트번호도 각각 80, 443을 사용하는게 특징이다.
3. HTTP/2.0을 통한 서버와 클라이언트의 연결 협약 과정
이제, HTTP/2.0이 클라이언트와의 통신에서 실제로 어떤 방식으로 연결을 맺는지 살펴보자. HTTP/2.0은 TLS(https)에서도 사용할 수 있고 http위에서도 사용 할 수 있는데, 우선 http 스킴으로 HTTP/2.0을 맺는 과정을 알아보겠다.
HTTP/2.0은 연결 협약을 맺는과정에서 기존의 HTTP/1.1프로토콜을 이용한다.
1. 클라이언트는 서버와 HTTP/1.1을 사용해 HTTP/2.0 연결을 맺는다. 요청의 예시는 아래와 같다. 클라이언트는 요청의 Upgrade헤더에 h2c를 포함하여 요청해야하고, HTTP2-Settings를 통해 Settings 을 명시해야한다.(Setting을 해석하려했는데, 마땅한 한국말이 떠오르지 않아 Setting 그대로 가져왔다. 원문이 주는 느낌을 통해 이해하는게 좋아보인다.)
GET / HTTP/1.1
HOST : server.example.com
CONNECTION : Upgrade, HTTP2-Settings
UPGRADE : h2c
HTTP2-Settings : <base64url encoding of HTTP/2 SETTINGS payload>
2. 클라이언트의 요청을 받은 서버는 HTTP 프로토콜로 "h2"(h2는 https를 통해 HTTP/2.0을 맺을때 사용하는 헤더임)가 들어오거나 HTTP/2.0을 지원하지 않는다면 요청을 무시한다. 만약 서버가 HTTP/2.0을 지원한다면, '101 Switch Protocol'응 답을 보낸다.
HTTP/1.1 101 Switching Protocols
CONNECTION : Upgrade
UPGRADE : h2c
이때, 서버는 SETTINGS 프레임(프레임은 HTTP/2.0의 가장 작은 메시지 단위로 일단 이해하도록 하자. 아래에서 더 자세히 설명하도록 하겠다.)으로 구성된 Connection preface응답을 클라이언트로 보낸다. 응답을 받은 클라이언트도 마찬가지로 SETTINGS프레임이 포함된 Connection preface응답을 보냄으로 HTTP/2.0통신이 시작하게 된다.
이제, https 스킴을 사용할때의 과정을 알아보자. https는 위에서 설명했듯이 h2c 식별자가 아닌 h2식별자를 이용한다.
우선 Client와 Server가 TLS협상을 진행하고, 이 다음 HTTP/2.0연결을 진행한다(이 과정은 http 스킴을 사용할때와 동일한듯 하다).
4. HTTP/2.0의 Header 압축 기술
HTTP/1.1과 마찬가지로 HTTP/2.0또한 key:value타입의 헤더 정보를 사용한다. Header정보가 Connection을 통해 전송될때, header list는 HTTP header compression을 사용해 직렬화된다. 직렬화된 header block들은 header block fragment라 부르는 것들로 분리된다. 결과적으로 압축된 헤더들은 '프레임' 이라고 부르는 단위에 각각의 특성에 맞게 분리되어 전달되며, 클라이언트와 서버가 스트림당 사용되는 하나의 key로 역 직렬화 한다.
5. HTTP/2.0 Streams와 Multiplexing
스트림은 HTTP/2.0 연결에서 Client와 서버가 frames를 교환하기 위해 사용되는것으로 각 스트림은 독립적이고 양방향이다. 이런 스트림에 중요한 특징 몇가지를 알아보자.
1. 하나의 HTTP/2.0 Connection은 여러개의 Stream을 '동시에' 열 수 있다.
2. Stream은 Server나 Client에서 일방적으로 열 수 있다.
3. Stream은 양 쪽 endpoint 모두에서 닫힐 수 있다. 한쪽(서버나 클라이언트)에서만 닫힐 경우 '반 닫힌 상태' 라고 표현하며 둘다 닫힌경우 '닫힌 상태'라고 표현한다. 열려있다면 '열린 상태' 이다.
Stream은 SETTINGS_MAX_CONCURRENT_STREAMS 파라미터를 통해 동시에 열 수 있는 스트림의 갯수를 제한할 수 있는데, 클라이언트가 서버측에서 열 수있는 스트림의 갯수를 제한하고 (클라이언트가 서버측을 제한) 서버측이 클라이언트측에서 열 수 있는 스트림의 갯수를 제한하는 식이다.
또한 스트림은 HEADERS프레임에 우선 순위 정보를 포함하여 스트림의 우선 순위를 할당할 수 있다.
6. HTTP/2.0 프레임
HTTP/2.0은 프레임 이라는 개념이 있는데, 프레임은 HTTP/1.1에 대응되는것들도 있고 HTTP/2.0만의 고유한것들도 있다. 이 부분은 매우 매우 비약해서(이 부분 읽다가 집중력이 떨어졌다.) 포스팅 하오니 프레임의 종류와 각 프레임의 역할이 자세히 궁금한 사람은 원문을 읽어보도록하자.
우선, 프레임에 대한 이해를 돕기위해 HTTP/1.1의 메시지 구조를 HTTP/2.0의 프레임으로 치환해보겠다.
만일 HTTP/1.1이 다음과 같은 구조를 갖고있다면,
GET / HTTP/1.1
HOST : server.example.com
CONTENT-TYPE : application/json
some...payload
HTTP/2.0에서는 아래와 같이 프레임이 생성된다.
---------HEADERS FRAME----------
GET / HTTP/1.1
HOST : server.example.com
CONTENT-TYPE : application/json
---------HEADERS FRAME----------
-----------DATA FRAME------------
some...payload
-----------DATA FRAME------------
또한, 압축과정에서 이진 압축방식이 사용되어 용량이 더 작아지게 된다.
이런 프레임에는 여러 종류가 있는데, 프레임의 종류와 설명은 아래와 같다.
1. DATA 프레임 : DATA FRAME은 응답 페이로드등을 전달하는데에 사용된다. 데이터 프레임에는 END_STREAM이라는 것이 있는데, 이 옵션이 설정되면, 스트림이 '반 닫힘' 혹은 '닫힘'상태로 들어간다.
2. HEADERS 프레임 : 헤더프레임은 스트림을 여는데에 사용되고, header조각을 운반하는데에도 사용된다. 스트림의 우선순위 설정을 여기서 진행할 수 있다, 또한, 헤더프레임에도 END_STREAM옵션이 존재한다.
3. PRIORITY 프레임 : priority프레임은 스트림의 우선순위를 정한다. (아니 HEAEDERS프레임에서도 정하고 여기서도 정하고 뭐 이리 겹치는게 많은지 모르겠다. 여러가지 선택지를 준 것 인가?)
4. RST_STREAM 프레임 : RST_STREAM 프레임은 스트림을 즉시 종료하는 프레임이다.
5. PUSH_PROMISE 프레임 : PUSH_PROMISE프레임은 서버가 클라이언트에게 스트림 시작을 알리는데 사용된다.(클라이언트가 서버로 보낼수는 없다.) 또한, PUSH_PROMISE는 '열림' 혹은 '반 닫힘' 상태의 스트림에서만 사용가능하다. 이 말은 누군가에 의해 이미 시작되었던 스트림을 통해서만 전달이 가능하다는 것 이다.
6. PING 프레임 : PING프레임은 발신자로부터 최소 왕복시간 측정과 연결이 여전히 보장되는지를 확인하는 프레임이다.
7. grpc는 왜 HTTP/2.0을 쳬택했을까?
(주의. 이 글을 작성하는 시점에서 나는 grpc에 대해 아무것도 모른다. 즉 지금부터 적을 grpc가 HTTP/2.0을 쳬택한 이유는 HTTP/2.0을 공부하고 적은 나의 주관이다 따라서 사실과 매우 다를 수 있으니 사실이 궁금하다면 구글에 물어보자)
사실 grpc가 HTTP/2.0프로토콜을 쳬택했다는것을 알게되었을때는 조금 의아했다. 아니.. MSA에서 HTTP가 갖는 (거대한 헤더로 인한 트래픽 증가, HOL로 인한 지연시간 증가)문제점 때문에 grpc를 공부하려한건데 돌고돌아 HTTP/2.0을 쓴다고? 하지만, HTTP/2.0에 대해 공부해보니 왜 쓰는지 감이 잡힌다.
우선 HTTP/2.0은 독립적인 스트림을 통해 여러개의 요청을 동시에 처리한다. 이는 여러개의 스레드가 원격서버의 프로시저를 동시에 호출했을때, HOL이 일어나는것을 방지해줄것이다.
둘째, HTTP/2.0은 양방향으로 서버1과 서버2가 HTTP/2.0 커넥션을 맺었다면, 누가 시작했던 상관없이 두 서버모두 양쪽의 프로시저를 호출할 수 있을것이다.
셋쩨, HTTP/2.0은 헤더 압축기술을 통해 빠른 전송 속도를 보장한다.
참고문서
(rfc 7540 공식문서)
https://httpwg.org/specs/rfc7540.html#FrameHeader
'grpc' 카테고리의 다른 글
[grpc] 4. grpc - Java (0) | 2022.09.08 |
---|---|
[grpc] 3. grpc의 기반기술 - Protocol Buffers와 성능 테스트 (0) | 2022.09.04 |
[grpc] 1. grpc의 기반기술 - RPC (0) | 2022.09.01 |