Back to the basic - gRPC

Jiyoon·2021년 10월 19일
1

MSA

목록 보기
1/1

1년 정도gRPC 기반의 프레임워크로 gRPC 통신을 통해 Microservices 중 몇가지를 개발했다. 프로토버퍼를 빌드하고, 배포도 해봤지만 그동안 뭔지도 잘 모르고 배포해왔다는 생각이 들어.. Back to the basic의 첫 시리즈로 gRPC를 공부해봤다.
사실 Back to the basic이 아니라 나같은 주니어한텐 Start from the basic이 더 맞을지도.

gRPC

특징

(1) Protocol Buffer

Server client 간 메시지를 정의하는 역할. 원래 REST API에서는 string / int.. 같은 자료형을 docs로 정의해서 노션이나 엑셀로 공유하고.. 했었다면 이 data 자체를 Code화 시킴.

실제 통신 시에는 byte stream으로 data를 encoding하여 통신.

통신 채널과 구현부가 분리되어서 서로 다른 언어로 구현 가능하다.

XML보다 작고, 경량화된 형태임.

(2) HTTP/2

속도 향상을 위해 Data를 나눠서 동시에 여러개를 보내고(Binary Framing) 요청 없이도 보내고 header도 줄이고..

(3) 양방향 스트리밍

Server / Client가 동시에 데이터를 스트리밍으로 주고받을 수 있음

출처: woori SASOO님 JHSong의 파이콘 발표영상


클라이언트가 바로 method 형식으로, 마치 로컬의 함수를 갖다 쓰듯이, 미리 정의된 프로토 버퍼 메시지의 response 대로 맞춰서 return을 받는다.

작동 방식

  1. Proto buffer를 작성하기 위한 언어(Google에서 정의한 IDL)를 배워 Proto buffer를 작성해 메시지를 정의한다.

  2. 각 언어에 맞게 proto buffer를 빌드하면 언어에 맞게 클래스가 떨어짐.

  3. Protobuf를 python에서 사용 가능하게 변환 (build). 예를 들어 user라는 API를 작성한다고 하면,

    • user_pb2.py와 : Message 정의에 사용될 class
    • user_pb2_grpc.py 가 결과물로 빌드됨 : Service 정의에 사용될 Class (UserServicer)
  4. protobuf를 통해 생성된 user_pb2_grpc의 Servicer를 상속 받아서 subclass로 구현 (ex. init, verify, parse.. )

  5. Server implementation

    server를 띄움 (서버측 grpc 서버)

    구현하고 있는 open source platform인 SpaceONE에서는 core의 server.py가 해주는건데.. server = grpc.server() server.start() 와 같은 grpc의 내장함수를 활용한다.

    https://github.com/spaceone-dev/python-core/blob/master/src/spaceone/core/pygrpc/server.py#L120

  6. Client implementation

    protobuf를 통해 생성된 user_pb2_grpc에 자동 생성된 Stub 클래스를 인스턴스로 생성해서 사용한다.

    class CollectorStub(object):
        """Missing associated documentation comment in .proto file."""
    
        def __init__(self, channel):
            """Constructor.
    
            Args:
                channel: A grpc.Channel.
            """
            self.init = channel.unary_unary(
                    '/spaceone.api.inventory.plugin.Collector/init',
                    request_serializer=spaceone_dot_api_dot_inventory_dot_plugin_dot_collector__pb2.InitRequest.SerializeToString,
                    response_deserializer=spaceone_dot_api_dot_inventory_dot_plugin_dot_collector__pb2.PluginInfo.FromString,
                    )
            self.verify = channel.unary_unary(
                    '/spaceone.api.inventory.plugin.Collector/verify',
                    request_serializer=spaceone_dot_api_dot_inventory_dot_plugin_dot_collector__pb2.VerifyRequest.SerializeToString,
                    response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                    )
            self.collect = channel.unary_stream(
                    '/spaceone.api.inventory.plugin.Collector/collect',
                    request_serializer=spaceone_dot_api_dot_inventory_dot_plugin_dot_collector__pb2.CollectRequest.SerializeToString,
                    response_deserializer=spaceone_dot_api_dot_inventory_dot_plugin_dot_collector__pb2.ResourceInfo.FromString,
                    )
    class Collector(BaseAPI, collector_pb2_grpc.CollectorServicer):
        pb2 = collector_pb2
        pb2_grpc = collector_pb2_grpc
    
        def init(self, request, context):
            params, metadata = self.parse_request(request, context)
    		def verify(self, request, context):
    				xxx... 이하생략
  7. python `server.py / client.py`

gRPC 를 사용하는 서비스에서 개발자가 할 일 한줄 정리

API source git clone받음

protobuf 작성

make python

결과는 dist 디렉토리에 생김

import해서 사용

단점

Protobuf는 Server / Client를 모두 갖고 있어야하고

잘게 쪼개진 Service의 경우 갖고 있는 Server/client... 모두 각자 관리해야 하며 이에 따른 복잡도가 좀 높아진다.

Protobuffer 버전 관리, 배포를 하는 경우 더욱 관리에 대한 복잡성이 있다.

Protobuf build가 쉽지는 않다. (build package간 dependancy check... ) 개발자 별 다른 환경..

단점을 극복하기 위해 만들어진 gRPC focused Framework인 SpaceONE →

API / Core / Service로 나뉜 gRPC focused framework : SpaceONE

지윤의 의문점과 Q&A

  • python run환경에서 spaceone.core.command -grpc spaceone.inventory해주는거 server측 gRPC server 띄워주는거 맞는지? → yes
  • server측 implementation 할때 실제로 server start하는 grpc.start()가 core package안에 core.serve() 안에 구현되어 있던데.. 호출해주는거 누구? trigger 해주는애 누구..? → trigger는 서버 런 할때 spaceone.core.command 호출할 때 https://github.com/spaceone-dev/python-core/blob/master/src/spaceone/core/command.py#L35 여기서
  • make python 해주는건 누구지..? 깃헙액션..? → YES github action에서 띄워주는 vm내의 환경에서 → 이것도 공부 필요
  • make python / dist 파일 어디에 생기는건지..? 도커 안에 생기면..? 그걸 pypi에 업로드하는건지? → YES wheel file로 업로드됨
  • space-connector도 other service랑 RPC 통신하면 stub 어디? core connector에..? → stub필요 없음
  • framework 이름 뭥미? → 처음에 pyengine 이었는데 딱히 없음

Note) SpaceONE의 grpc server implement 과정에서 다양한 config 파일들이 합쳐지는 과정

conf를 띄울 때는 spinnaker의 helm values (from.gitlab) + core의 conf + plugin의 global_conf(https://github.com/spaceone-dev/plugin-azure-cloud-service-inven-collector/blob/master/src/spaceone/inventory/conf/global_conf.py)가 합쳐져서 돌아감 이 모든건 grpc server를 띄우기 위한 configuration 작업임.

실제로 inventory 서비스가 배포된 pod에 들어가서 보면 (kubectl exec -it ~ ) conf 보면 디폴트만 있고 config값들은 opt/spaceone directory 아래 모아져 있음

Note) SpaceONE Framework 구조 및 역할

  • API : proto buffer 관리 pkg: protobuf build를 위해 필요한 패키지 List package 소스 파일 proto build dist template
  • Core
  • Service
profile
Jiyoon in cloud valley, Change the world Why Not? / 오픈소스 생태계를 잘 이해하는 Cloud engineer가 되고 싶은 지윤

0개의 댓글