[gRPC] gRPC 소개 - 2

iguigu·2022년 4월 8일
1

gRPC

목록 보기
2/2

Overview

  • gRPC는 ProtoBuf를 IDL (Interface Definition Language)와 메세지 교환 포맷으로 사용 가능. 즉 gRPC는 원격 프로시저 호출 시스템이고, ProtoBuf는 인터페이스 정의 언어
  • 전송을 위해 HTTP/2 사용. 그렇기 때문에 기본적으로 외보에서 노출되어야 하며, 로드밸런서가 필요한 경우 로드밸런서가 HTTP/2를 지원해야함
  • gRPC는 원격에서 호출될 수 있는 매서드를 service로 정의 함
  • 서버는 인터페이스를 구현하고 클라이언트의 호출을 처리하기 함
  • 클라이언트는 서버와 동일한 method를 제공하는 gRPC stub를 가짐

Features

  • 다양한 언어 지원
  • 내부적으로는 Netty(소켓 통신) 이용
  • 동기식 요청-응답/ 완전 미동기 / 스트리밍 등 다양한 통신 방식 지원
  • 통신 방식
    • unary : request/reponse를 1회 받을 때만 TCP 커넥션을 맺고 처리하는 방식 (HTTP 방식과 유사하지만 gRPC의 unary가 성능은 훨씬 좋음)
    • stream : 지속적으로 데이터를 보내고 받는 소켓 통신과 같이 사용 가능

Core Concept

gRPC Service

gRPC는 ProtoBuf를 service interface와 payload message를 표현

// service interface
service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

// payload message
message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}
  • gRPC 4가지 service method
    • 서버(1) : 클라이언트(1)
      • 단일 request, 단일 response
        rpc SayHello(HelloRequest) returns (HelloResponse);
    • 서버(N) : 클라이언트(1)
      • request 후 메세지 스트림을 response를 받음 (메세지가 끝날 때 까지 읽음)
        rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    • 서버(1) : 클라이언트(N)
      • 메세지 스트림을 계속 보냄. 클라이언트가 Msg를 그만 보내면, response를 받음
        rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    • 서버(N) : 클라이언트(M)
      • 양방향 스트리밍 RPC. 두 스트림은 독립적으로 동작함
        rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

RPC lifecycle

gRPC는 service method 종류에 따라 lifecycle이 다름

가장 단순한 RPC의 경우 (단일 request, 단일 response)

  • client가 stub method를 호출하면 서버는 클라이언트 정보 (metadata, method name, deadline 등)를 가진 채 RPC를 알게 됨
  • 서버는 이전에 reponse로 보냈던 metadata를 보내거나 client의 request 메세지를 기다릴 수도 있음
  • 일단 서버가 클라이언트의 메세지를 받으면, response를 만들 일들을 수행함.
  • 만약 response가 OK면, 클라이언트는 response를 받고, call을 성공적으로 마무리 함

이외의 다른 종류의 RPC의 경우에는 여기 참조

gRPC API

gRPC를 이용한 API 구현이 가능함

  • .proto 파일을 통해 gRPC는 server/client 코드를 제공함
  • 해당 API를 통해 server와 client가 통신 할 수 있음
  • 이 때 동기/비동기 통신 모두 지원 가능

Usage

proto file

  • message : 데이터를 주고 받을 포맷
  • repeated : Array로 string item을 여러개 받겠다는 의미
  • service : 실제 데이터 통신을 어떻게 주고 받을지 정의. 웹서비스의 API 정의서
    • rpc updateOrders의 경우 Order 메세지를 지속적으로 보내고 서버는 unary로 응답
    • rpc processOrders의 경우 input과 output 모두에서 stream을 넣어 양쪽 세션 유지

protoc

  • protoc를 활용한 컴파일
  • 빌드 완료시 protofile.pb.go 파일 생성
# protoc 설치 후 go 언어로 빌드하기 위해 protoc-gen 사용
go install google.golang.org/protobuf/cmd/protoc-gen-gogo

# proto compile 
protoc -I . protofile.proto --gogo_out=.

protofile.pb.go

  • proto file에서 정의한 메세지 형식과 통신 방식을 go 언어로 생성
  • protoc를 통해 자동 생성된 이 파일은 절대 수정하지 말 것
  • getter, setter 등이 필요하다면 extension 기능을 활용할 것
  • protofile.pb.go 내의 매서드는 손쉽게 코드 내에서 활용 가능

gogoproto

  • size, marshaler, getter, setter등 자동으로 만들어 주는 오픈소스
    • pb.go 파일 내에 getter, setter 등 필요한 부분이 생길 수 있음
    • 직접 수정할 경우 타입이 맞지 않는 에러 발생하고, 원인을 찾기 힘들어 짐
  • gogoproto option을 추가하여 protoc로 컴파일할 경우 원하는 코드가 생성됨
    • 아래 그림과 같이 marshaler가 생성됨을 확인 가능

  • 이외에도 nullable, customtype, customname 등 다양한 옵션 존재
    • nullable : omitempty가 없어지게 됨. nullable이 없는 상태에서 null일 경우 panic 발생
    • customtype, customname : 새롭게 직접 정의해서 사용하고 싶은 경우
  • gogoproto 등 import한 proto 파일을 컴파일 할 때 옵션을 설정해줘야함. 그렇지 않으면 undefined 에러 발생
# gogoproto와 googleapis를 import 해서 빌드하는 protoc command
# -I 옵션은 --include_imports 플래그
protoc -I=./github.com/gogo/protobuf -I=./googleapis -I=. --
gofast_out=plugins=grp:output/ test/test.proto

Reference

profile
2929

0개의 댓글