Skip to content

juneyr.dev

gRPC 뽀개보기

network, gRPC3 min read

gRPC 란

분산시스템에서 다른 머신의 서버 어플리케이션에 있는 메소드를 자신이 갖고 있는 것 처럼 호출할 수 있게 해주는 프레임워크. 대부분의 RPC 처럼 원격으로 호출가능한 Service 를 정의하는 성질을 갖고 있음. 서버 사이드에서는 이 프레임워크를 차용해서 client call을 대응할 수 있도록 gRPC 서버를 운영한다. 클라이언트 사이드에서는 stub (서버에 있는 메소드를 동일하게 제공하는 , 다른 언어의 클라이언트) 를 갖고 있다.

왜 쓰는데? 참조

gRPC는 HTTP/2를 기반으로 통신합니다. HTTP/2에서는 양방향 스트리밍이 가능합니다. 즉, 일반적인 요청/응답 방식이 아니고 서버와 클라이언트가 서로 동시에 데이터를 스트리밍으로 주고 받을 수 있다는 것 입니다.

높은 메시지 압축률과 성능 HTTP/2의 또다른 장점 중 하나는 HTTP를 사용하는 전송보다 높은 헤더 압축률을 보장한다는 점입니다. gRPC에서는 HTTP/2에 의한 압축뿐만 아니라 protoBuf에 의한 메시지 정의에 의해서 메시지 크기를 획기적으로 줄일 수 있습니다. 메시지의 크기가 줄어드는 것은 곧 네트워크 트래픽이 줄어드는 것을 의미하기 때문에 시스템 리소스를 절약하고 성능을 높일 수 있습니다.

직렬화 매커니즘

gRPC는 기본적으로 protocol Buffer를 사용한다. Protocol Buffer는 .proto 확장자를 사용하는 txt 파일에 직렬화(serialize)하고자 하는 데이터 구조를 정의한다.

이렇게 proto 파일을 정의하고 나면, protocol buffer compiler인 protoc를 사용해서 원하는 언어로(proto 파일 안에 정의해둔 언어로) 컴파일 할 수 있다. 예를 들어 c++를 선택하면 message Person은 Class Person으로 컴파일 된다.

gRPC 기본 개념

4가지 service method

  1. Unary RPC
    서버에 single request를 보내면, 서버는 single response를 돌려준다. (일반 함수 호출과 같음)
  1. Server streaming RPC 서버에 single request를 보내면, 서버는 stream을 돌려준다. Stream에는 message 시퀀스가 들어있다. 클라이언트는 더 이상의 message가 없을 때까지 stream을 읽어들인다.
  1. Client streaming RPC 클라이언트가 주어진 stream을 이용하여 message sequence를 서버에 보낸다. 클라이언트는 메시지들을 모두 작성하고 나면, 서버가 읽고 response를 주기를 기다린다.
  1. 양방향 streaming RPC Read-write stream을 사용하여 클라이언트와 서버 두 측 모두 message sequence를 보낸다. 두 stream은 독립적으로 동작하여, 클라이언트와 서버는 원하는 순서대로 읽어들일 수 있다. 예를 들어 서버는 클라이언트의 모든 메시지를 읽은 뒤 response를 write할 수도, 아니면 번갈아 가며 한 메시지씩 읽고 쓸 수도 있다. 각 stream에서 메시지의 순서는 보존된다

API 사용하기

gRPC는 .proto 파일에 정의된 service 로 부터 client와 server side code를 만들어주는 protocol buffer compiler를 제공한다.

  • 서버사이드 : 서버는 service에 정의된 method를 구현하고, 클라이언트의 호출을 대응하기 위해서 gRPC 서버를 운영한다. gRPC 구조가 들어오는 요청을 디코드하고, 서비스 method를 실행하며, service response를 인코드해준다.
  • 클라이언트 사이드: 클라이언트는 (일부 언어에서는) stub이라고 불리는 로컬 오브젝트를 갖고 있다. stub은 서비스에 정의된 것과 같은 method를 구현한다. 클라이언트는 파라미터를 적절한 protocol buffer type으로 만들어 stub에 있는 method를 호출하기만 하면 된다. gRPC가 서버로 요청 전송과 응답 반환을 관리해준다.

동기 vs 비동기

서버에서 응답이 올때까지 block 하는 동기식 RPC 호출은 RPC가 원하는 프로시져 콜의 추상화에 가장 가깝다. 그러나 네트워크는 근본적으로 비동기식이고, 대부분의 경우 RPC가 현재 쓰레드를 블락하지 않도록 하는 것이 도움이 된다.

gRPC는 동기와 비동기를 둘다 지원한다.

RPC 생명 주기

  • Unary RPC
  1. 클라이언트가 stub에 있는 메소드를 호출하면, 서버는 RPC가 동작한다는 알림을 받는다. 이때 클라이언트의 메타데이터, 메소드 이름, 그리고 (가능하다면) 데드라인이 명시된다.
  2. 서버는 (response 전에 보내야하는) 스스로의 메타데이터를 바로 보내주거나, 혹은 클라이언트의 요청 메시지가 있을때까지 기다린다. 어떤 것이 먼저 일어날지는 어플리케이션에 따라 다르다.
  3. 서버가 클라이언트의 요청 메시지를 받으면, response를 생성한다. client에 response를 전달 시, status code와 (옵션) status message, (옵션) meta 데이터가 따라 붙는다.
  4. Status 가 OK면 클라이언트를 response 받고, 이로서 client 쪽의 호출은 끝난다.
  • Server streaming RPC, Client streaming RPC 한쪽이 stream of response 혹은 stream of request 를 보낸다는 점을 제외하면, Unary RPC와 동일하다.

  • Bidirectional streaming RPC 클라이언트가 호출하고, 서버가 메타데이터와 메소드, 데드라인을 받은 후, 서버에서는 스스로의 metadata를 보낼지 혹은 클라이언트가 요청을 전송하는 것을 기다릴지 선택한다.

이후에는 application에 다라 다른데, 클라이언트와 서버가 읽기와 쓰기를 어떤 순서로도 할 수 있기 때문이다. stream은 독립적으로 운영되므로 서버는 요청이 모두 올 때 까지 기다리거나 클라이언트와 핑퐁을 할수도 있다.

데드라인 / 타임아웃

위에서 클라이언트가 메소드 호출 시에 ~데드라인~ 이 포함된다고 했다. gRPC는 클라이언트들이 RPC 호출을 얼마나 기다릴 수 있는지 적을수 있게 했다. (DEADLINE) 서버 측에서는, 특정 RPC가 타임아웃되었는지 혹은 RPC를 마칠때까지 얼마나 남았는지 쿼리할 수 있다.

RPC 종료

gRPC에서는 클라이언트와 서버가 RPC의 성공여부에 대해서 독립적이고 지역적인 판단을 내리고, 이 결론은 서로 맞지 않을 수도 있다. 이는, 서버에서는 “ 나 내 response 다 보냈음 하하하하하 !” 해서 성공해도, 클라이언트에서는 “response 데드라인 이후에 왔어 ;(“ 할 수도 있다는 것을 의미한다.

RPC 취소하기

클라이언트나 서버 둘다 RPC를 언제든지 종료할 수 있다. 취소 액션은 RPC를 바로 종료하여 추가적인 작업이 없도록 한다. 취소는 ‘undo’의 개념은 아니다.

Metadata

메타데이터는 RPC call에 대한 정보이다(주로 string key- string value 형태를 띔)

Channel

gRPC 채널은 특정 호스트와 포트에, gRPC 서버와의 연결을 제공한다. 채널은 client stub을 생성할 때 사용한다. 클라이언트는 기본 gRPC 형태를 변경하는 채널 인자를 설정할 수 있다. 예를 들어 메시지 압축 옵션 등. 채널은 connectedidle 상태를 포함하여 상태값을 갖는다.

어떻게 채널을 닫는지는 언어에 따라 다르다.

인증 (Authentication)

gRPC는 두가지 인증 매커니즘을 지원한다.

  • SSL(Secure Socket Layer) / TLS(Transport Layer Security) 서버를 인증하고, 클라이언트와 서버 간 교환된 모든 데이터를 암호화하는데 사용한다.

  • Token기반 인증 (with Google) Google API 에 gRPC 접근할때는 OAuth2 token과 같은 access token이 필요하다. 여기서도 channel은 SSL/TLS로 보안됨.

인증 API

gRPC는 전체 gRPC 채널을 생성하거나 개별 call을 만들 때 사용되는 Credentials 오브젝트에 기반하여 인증 API를 제공한다.

Credential 종류

  • Channel Credentials SSL Credentials 과 같이 채널에 붙는 종류
  • Call Credentials Call에 붙는 종류

CompositeChannelCredentials 를 이와 결합하면, 채널에 대한 SSL 사항 등을 설정할 수 있습니다.

Client-side에서 SSL/TLS 사용하기

  • 기본 SSL ChannelCredential Object 를 생성한다
  • Credential을 사용하여 Channel을 생성한다
  • channel에 stub을 생성한다
  • 실제 RPC 호출을 한다.

Google token-based authentication

  • GoogleDefaultCredentials 오브젝트를 생성
  • 나머지는 위와 같음

파이썬 예제

01 암호화나 인증없을 경우

02 SSL/TLS 적용