gRPC 분석

jingyu·2022년 6월 28일
0

Golang

목록 보기
2/3

gRPC 공부 내용

gRPC란?

gRPC 대신에 흔히 가장 많이 사용되는 것이 JSON을 사용한 HTTP API이다. HTTP API는

Client ←→ Server
Server ←→ Server
간 서로 데이터를 주고 받을 때 사용되는 통신 방법이라고 생각할 수 있다.

아래 예제에 Client가 HTTP로 RESTful하게 서버에게 GET으로 요청 한다.

그리고 서버는 요청에 대해 JSON으로 결과값을 전달하게 된다. (HTTP와 REST라는 개념은 거의 항상 붙어다녀서 사용된다,)

HTTP API는 데이터를 서로 주고 받을때 사용된다.

gRPC는 HTTP API 통신과 비슷하지만 차이점은 Proto Request를 전달하고 JSON 대신 Proto Response를 전달하는 것으로 생각한다.
큰 틀에서 봤을때 HTTP와 마찬가지로 데이터를 주고받는 방식 중 하나라고 볼 수 있다.

RPC(Remote Procedure Call)는 원래 분산환경 시스템에서 서로 다른 컴퓨터 프로그램들이 서로 다른 주소에서 서로를 호출하지만 마치 같은 주소에서 호출하는 것처럼 작동하게 하는 원격 프로시져 프로토콜이다.

즉, 프로그램들은 서로가 누구인지 알 필요 없이 정해진 방식대로 단순히 함수 호출만 하면 되는 것이다.

위 그림에서 Ruby Client는 통신하고 있는 C++ Service가 어느 위치에 있던, 어떤 코드로 작성되었던 간에 상관 없이 정해진 Proto라는 규격만 있으면 자유롭게 데이터를 주고 받을 수 있는 것이다.

그렇다면 gRPC는 무엇일까?

Google이 만든 protobuf(a.k.a protocol buffer)라는 방식을 사용해 RPC라는 프로토콜로 데이터를 주고 받는 플랫폼을 의미한다.

gRPC의 장점

1) 빠르다

protocol buffer라는 방식은 XML과 같이 구조화된 데이터를 직렬화(serialize)하는 방식인데 압축을 해서 훨씬 빠르고, 사용법도 간단하고, 데이터의 크기도 작다.
JSON 직렬화보다 최대 8배 더 빠를 수 있다고 한다

2) 엄격한 사양 덕분에 생기는 가이드의 존재 유무

gRPC로 통신하기 위해서는 protocol buffer로 어떻게 데이터를 주고 받을 것인지 정의해놔야 한다.
그렇기 때문에, 데이터를 주고 받을 때는 어떤 형식으로 전달해야하는지에 대한 가이드가 코드로 생성되기 때문에 따로 API 문서같은 것을 만들 필요가 없게 되는 것이다.
여러 회사에서도 이런 엄격한 사양 덕분에 개발 생산성이 높아지는 이유도 있어서 gRPC를 사용하는 경우가 다수 있다. ref. 뱅크샐러드 기술 블로그

3) HTTP/2

RPC는 HTTP/2를 지원한다.
gRPC는 HTTP/1.1과 호환되지만 HTTP/2만의 고급 기능들도 사용할 수 있다.
동일한 연결로 병렬적인 요청을 처리할 수 있고, 연결을 유지해서 connection을 매번 하는데 사용되는 cost도 줄일 수 있다.

gRPC의 이러한 장점들은 요새 유행하고 있는 Microservice에 안성맞춤이다. Microservice는 간단히 말하면 서비스의 모든 기능들을 하나의 큰 서버에 몰아놓는 것이 아닌, 각각의 독립적인 기능으로 여러 서버로 만들고 서버들간 통신하게 만드는 아키텍처를 의미한다

gRPC의 단점

1) 일단 가장 크게 브라우저와 서버간은 gRPC통신이 아직 지원되지 않는다.

2) 그래서 브라우저에서는 흔히 JSON으로 서버로 요청하면 서버는 grpc-gateway를 통해 protobuf 형식으로 데이터를 변환한 뒤에 사용하게 된다.

3)사람이 읽을 수 없는 데이터 형식이기 때문에 네트워크 단에서 데이터를 보고 싶으면 추가적인 작업들이 필요하다.

gRPC와 HTTP 비교

gRPC 사용 및 흐름

1) 실행하고자 하는 프로시저와, 전달하고자 하는 파라미터 사양을 .proto 파일로 작성합니다.

2) protoc 를 통해 사용하고자 하는 언어에 맞게 stub 파일을 생성합니다.

생성된 파일은 각 클라이언트가 참조할 수 있는 언어(.java .c .go 등..) 로써 bean 과 같이 데이터를 엑세스 하거나 핸들링하는 함수가 포함되어 있습니다.

3) gRPC 에서 각 언어별로 제공하는 SDK를 제공합니다. 이를 활용해 서버, 클라이언트를 프로그래밍 합니다.

stub 을 활용해 실행될 프로시저를 구현하거나 전달할 파라미터를 생산할수 있습니다.

  • .proto 와 stub 파일
    protocol buffer 를 사용하는 이점중 하나는 .proto 파일로 구조화된 데이터를 작성하기만 한다면 gRPC가 지원하는 어떤 언어에서든 규약에 상관없이 통신이 가능하다는 것입니다.
    작성된 .proto 로부터 언어에 맞는 stub을 생산하여 참조하게 되면 이후 별도의 사양서를 볼 필요없이 참조한 stub 만으로도 개발이 가능합니다.

예제

config/config.proto

syntax = "proto3";
 package test;
 
service Test {
  rpc GetSum(Data) returns (Sum) {}
}
 
message Data {
  int32 a = 1;
  int32 b = 2;
}
 
message Sum {
  int32 sum = 1;
}

server.py

from concurrent import futures
 
import grpc
 
from python_out.service_pb2 import Data, Sum
import python_out.service_pb2_grpc as service_pb2_grpc
 
 
class TestServicer(service_pb2_grpc.TestServicer):
    def __init__(self):
        pass
 
    def GetSum(self, request: Data, context):
        print('a:{0}  b:{1}'.format(request.a,request.b))
        return Sum(sum=request.a + request.b)
 
 
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    service_pb2_grpc.add_TestServicer_to_server(
        TestServicer(), server
    )
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()
 
 
if __name__ == '__main__':
    serve()

run.py

from grpc_tools import protoc
 
protoc.main((
    '',
    '-Iprotos',
    '--python_out=.',
    '--grpc_python_out=.',
    'protos/service.proto',
))

client.py

import grpc
 
import python_out.service_pb2 as service_pb2
import python_out.service_pb2_grpc as service_pb2_grpc
 
 
def get_sum(stub: service_pb2_grpc.TestStub):
    response = stub.GetSum(service_pb2.Data(a=1, b=2))
    print(f"Received sum: {response}")
 
 
def run():
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = service_pb2_grpc.TestStub(channel)
        print("-------------- Get Sum --------------")
        get_sum(stub)
 
 
if __name__ == '__main__':
    run()

gRPC Gateway

gRPC는 브라우저-서버 간의 통신이 지원되지 않는 단점이 존재하는데 이는 gRPC-Gateway를 이용하면 해결할 수 있다.

gRPC-Gateway는 프로토콜 버퍼 컴파일러(protoc)의 플러그인이다.

gRPC 서비스 정의(proto file)을 읽고 리버스 프록시 서버를 생성하는데 이 서버가 RESTful HTTP API를 gRPC로 변환해주는 역할을 한다.

아래 그림은 gRPC 클라이언트(Stub)과 리버스 프록시 서버를 생성한 뒤 RESTful HTTP API 요청을 gRPC로 변환하는 것이다.

참고

https://devjin-blog.com/golang-grpc-server-1/

https://docs.microsoft.com/ko-kr/aspnet/core/grpc/comparison?view=aspnetcore-6.0

좋아요처음으로

profile
내일을 향해 쏴라!

0개의 댓글