마이크로 서비스와 gRPC를 활용한 서버 간 통신 적용기

배우다·2021년 4월 29일
5

gRPC

목록 보기
1/1

지금 회사의 아키텍쳐는 마이크로서비스 아키텍쳐 구조로 되어 있다. 지금 구조에서 Client 와 Server 간 통신에는 큰 문제 없었으나, 마이크로서비스 간의 통신을 할 때가 문제였다. Rest Api 방식으로 통신이 가능 했으나 마이크로서비스간의 인증 문제와 서버간의 통신을 좀 더 빠르고 안전하게 다룰 수 있는 방법을 찾아보기로 하였다. 그 중 찾은 방법은 gRPC 프레임워크를 사용한 서비스간의 통신 방법을 찾았다.

현재 gRPC에서 특징인 HTTP/2, 프로토콜버퍼는 현재 브라우저에서 많은 지원을 하지 않기 때문에 클라이언트 단은 Rest API로, 마이크로서비스 간 통신은 gRPC로 하기로 하였다. gRPC를 이용하기 전에 RPC가 정확히 어떤 것인지 이해가 필요해 조사를 조금 해보았다.


RPC (Remote Procedure Call) 란?

RPC는 Remote Procedure Call의 약자로 네트워크로 연결된 서버 상의 프로시저(함수, 메서드등)을 원격으로 호출할 수 있는 프로세스 간 통신 기술이다. RPC를 이용하면 프로그래머는 원격지의 자원을 내 것처럼 사용 할 수 있다. IDL(Interface Definition Language) 기반으로 다양한 언어를 가진 환경에서도 쉽게 확장이 가능하며, 인터페이스 협업에도 용이하다는 장점이 있다.

* IDL 이란 한 언어에 국한되지 않는 언어중립적인 방법으로 인터페이스를 표현함으로써, 같은 언어를 사용하지 않는 소프트웨어 컴포넌트 사이의 통신을 가능하게 한다.

※지원 언어: C++, Java, Python, Ruby, Node.js, C#, Go, PHP, Objective-C ...

Stub 이란?

RPC의 핵심 개념이다. 서버와 클라이언트는 서로 다른 주소 공간을 사용하므로, 함수 호출에 사용된 매개 변수를 변환해야 된다. 이때 Stub을 사용하여 매개 변수를 변환 한다.

  • Client stub : 함수 호출에 사용된 파라미터의 변환(Marshalling, 마샬링) 및 함수 실행 후 서버에 전달 된 결과 변환을 담당한다.

  • Server stub : 클라이언트 요청시 전달한 매개 변수의 역변환(Unmarshalling, 언마샬링) 및 함수 실행 결과 변환을 담당한다.

Stub을 이용한 RPC의 통신 과정

RPC 구조 (출처 :https://middlewares.files.wordpress.com/2008/04/17.jpg)

① IDL(Interface Definition Language)을 사용하여 호출에 대한 인터페이스를 정의한다.

  • 함수명, 인자, 반환값에 대한 데이터형이 정의된 IDL 파일을 rpcgen으로 컴파일하면 stub code가 자동으로 생성된다.

② Stub Code에 명시된 함수는 원시코드의 형태로, 상세 기능은 server에서 구현된다.

  • 만들어진 stub 코드는 클라이언트/서버에 함께 빌드한다.

③ Client stub은 RPC 런타임을 통해 함수를 호출 한다.

④ Server는 수신된 procedure 호출에 대한 처리 후 결과 값을 반환한다.

⑤ 최종적으로 Client는 Server의 결과 값을 반환받고, 함수를 Local에 있는 것 처럼 사용할 수 있다.


gRPC (google Remote Procedure Call) 란?

gRPC는 Google이 개발한 고성능 오픈소스 범용 RPC 프레임워크이다. gRPC에서 클라이언트 애플리케이션은 다른 머신의 서버 애플리케이션에 있는 메소드를 로컬 객체처럼 직접 호출할 수 있으므로 분산 애플리케이션 및 서비스를 더 쉽게 만들 수 있다.

gRPC는 HTTP/2를 사용하고 프로토콜 버퍼로 데이터를 전달한다. 그렇기에 Proto fILE만 배포하면 환경과 프로그램 언어에 구애받지 않고 서로간의 데이터 통신이 가능하다.

HTTP/2 기반의 양방향 통신.

  • HTTP/1은 클라이언트의 요청이 올때마다 connection을 생성해야 하지만 HTTP/2는 한 conection으로 통신이 가능하며 서버와 클라이언트가 서로 동시에 데이터를 주고 받을 수 있다.

  • 높은 Header 압축률을 보장하고 중복을 제거 하기에 HTTP/1에 비해 훨씬 효율적이다.

  • 클라이언트 요청 없이도 서버가 리소스를 전달 할 수 도있기 때문에 클라이언트 요청을 최소화 할 수 있다.

ProtoBuf (Protocol Buffer, 프로토콜 버퍼)

  • Protocol Buffer는 google 사에서 개발한 구조화된 데이터 직렬화 기법을 말한다.
    * 직렬화란 데이터 표현을 바이트 단위로 변환하는 작업을 말한다
  • Protocol Buffer로 직렬화 할 경우 필드 번호, 필드 유형 등을 1byte로 받아서 식별하고, 주어진 length 만큼 읽도록 하여 용량을 최소화 한다.

Json vs Protocol Buffer 데이터 비교 (그림 출처 :https://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html)

Proto File

1. Message and Field : ProtoBuf를 통해 주고받는 데이터들은 message를 통해 정의한다. 이 메시지는 여러 타입의 Field로 구성된다.

syntex = "proto3";

message Request {
	string feild1 = 1;
    int32 field2 = 2;
    int32 filed3 = 3;
}

▶ Field Tag (= Field Number)
- 메시지에 정의돈 필드들은 각각 고유한 번호를 가지게 되고 이는 Encoding 이후 binary data에서 필드를 식별하는 데 사용된다.
- Field Tag는 최소 1, 최대 536,870,911(=229-1)로 지정 가능하며, 19000~19999 는 프로토콜 버퍼 구현을 위해 제한된 값이므로 사용할 수 없다.

▶ syntax
- syntax는 어떤 버전의 문법을 따를지 선언할 수 있다. 명시하지 않을 시 default로 proto version 2 문법을 따른다.
- Proto 2는 C++, Java, Python, Go를 지원.
- Proto 3은 C++, Java, Python, Go, Ruby, Objective-C, C#, JavaScript, PHP, Dart를 지원

▶ Proto File Field Rule
- required : 필수로 가져야 할 필드 (only use proto2)
- optional : 해당 필드를 가지지 않거나 하나만 가짐 (only use proto2)
- repeated : 임의 반복 가능한 필드 (번호 및 값의 순서는 보존)
* [packed=true] 옵션 : key-value 쌍 형태에서 value만 반복

2. Package

  • Package는 message 충돌 방지를 위해 설정이 필요하고, 프로그래밍 언어마다 generate 할 때 어떻게 적용하는 지가 다르다
  • 자바는 option java_package"; 를 지정하지 않으면 자바패키지로 사용한다.

3. Service

  • Service는 RPC를 통해 서버가 클라이언트에게 제공할 함수의 형태를 정의한다.
  • 서비스명과 RPC 메소드명 모드 CamelCase 형태를 권장한다.
  • stream 옵션을 주면 양방향 streaming RPC를 구현할 수 있다.
// Unary RPC
service Greeter {
  rpc SayHello ( HelloRequest ) returns ( HelloReply ) {}
}

//양방향 Streaming RPC
service FileService {
  rpc FileUpload ( stream FileUploadRequest ) returns ( FileUploadReply ) {}
}


참고 문서.

[NBP 기술&경험] 시대의 흐름, gRPC 깊게 파고들기 #1

구글 gRPC 문서

Protocol Buffers Language Guide [기본기를 쌓는 정아마추어 코딩블로그]

profile
안녕하세요. JAVA, SPRING, VUEJS, NUXT 사용하는 백엔드 개발자입니다.

0개의 댓글