gRPC란?
HBase에서 RPC통신이 나오는데 문득 사내 wiki에 작성했던 내용인 gRPC가 블로그에 포스팅이 없어서 퍼왔습니다:)
아래 스터디할때 만들었던 소스도 있으니 참고하세요~:)
IPC
process는 기본적으로 상호독립적인데 process간 메모리를 공유하지는 않지만 필요에 따라 서로 정보를 공유해야하는 경우
별도 수단을 마련해서 process통신을 하게 되었는데 이를 IPC(Inter Process Communication)라고 부릅니다.
Socket
- OSI 7계층의 Application Layer에서 Transport Layer의 TCP/UDP를 이용하기 위한 수단이다.
- local 컴퓨터의 프로세스와 remote 컴퓨터의 프로세스가 IPC 통신을 하는 개념이다.
- 대부분의 언어에서 API 형태로 제공되기 때문에 多 쓰이지만, 통신과정 구현과 장애처리는 개발자의 몫이다.
RPC
- 이런 소켓의 한계점을 극복한 원격 함수 호출 방법이다.
- 같은 네트워크로 연결된 서버 상의 함수를 내 것처럼 원격 호출한다.
- 통신이나 Call방식, 이런 세세한 것들은 신경쓸 필요 없다.
- 지원 언어 : Java, Go, Python, Node.js, C++ 등등
- Stub : RPC의 핵심 개념.
- 매개변수 객체를 메세지로 변환(Marshalling)/역변환(unMarshalling)하는 레이어이며 Client Stub과 Server Stub으로 나뉩니다.
- Client Stub은 함수호출에 사용된 파라미터의 변환 및 함수 실행 후 서버에서 전달 된 결과의 변환을 담당 합니다.
- Server Stub은 Client가 전달한 매개변수의 역변환 및 함수 실행 결과 변환을 담당 합니다.
- java : RMI(Remote Method Invocation)
gRPC history
google은 스터비(Stubby)라는 범용 RPC프레임워크를 사용해 여러 데이터센터에 있는 서로 다른 기술로 구축된
수천개의 마이크로서비스를 연결했는데 핵심 RPC계층은 초당 수천억 건의 인터넷상 요청을 처리할 수 있도록 설계했습니다.
스터비에는 훌륭한 여러 기능이 있지만 구글의 내부 인프라에 너무 종속적이어서 범용 프레임워크로 표준화되지 못했습니다.
이후 구글은 2015년도에 오픈소스 RPC 프레임워크로 gRPC를 출시 했는데 표준화되고
범용적인 크로스 플랫폼 RPC 인프라를 담당 합니다.
gRPC는 넷플릭스, 스퀘어, 리프트, 도커, 시스코, CoreOS등 주요 기업의 대규모 도입으로 지난 몇년 동안 크게 성장하였습니다.
gRPC?
google Remote Procedure Call로 구글에서 제공하는 RPC 프레임워크 입니다.
이전까지는 RPC 기능은 지원하지 않았고, JSON 등 메시지를 Serialization해주는 Protocol Buffer 프레임워크만을 제공해 왔는데, HTTP/2와 결합하면서 RPC 기능을 지원하는 RPC 프레임워크가 되었다고 합니다.
Protocal Buffer
- protocal buffer는 구조화된 데이터를 직렬화하기 위한 구글의 언어 중립적, 플랫폼 중립적 확장 가능한 메커니즘을 말합니다.
- 보통 xml이나 json을 생각할 수 있지만 더 작고 빠르고 간단합니다.
- protocal buffer를 통해 데이터를 주고 받을수 있고 이를 통해 어떤 언어나 플랫폼에서도 통신 프로토콜 등에
쉽게 적용할 수 있습니다.
사용이유?
가장 큰 이유는 MSA아키텍처에 유용하기 때문 입니다.
SOA(서비스 지향 아키텍처)에서는 SOAP라는걸 사용했다면 MSA에서는 gRPC!!
또한 2가지 특징 때문이라 생각 합니다.
- 높은 성능
- gRPC는 HTTP/1.1과 비교하여 최대 10배의 성능 향상을 제공
- 다양한 언어 및 플랫폼 지원
- 명확하고 엄격한 점검 가능
구조
gRPC는 Application, Framework, Transport Layer로 나눠져 구성되어있으며 Http2.0 기반 위에 올라가져 있습니다.
특징
gRPC는 HTTP/2를 기반으로 구현되어 있어 HTTP/1.1보다 효율적인 데이터 전송을 제공합니다.
gRPC는 여러 서브채널을 열어서 통신하며 이 채널을 재사용함으로써 통신비용을 절약할 수 있습니다.
HTTP/2는 다음과 같은 기능을 제공하여 데이터 전송을 효율화 합니다.
- 압축: HTTP/2는 데이터를 압축하여 전송하여 네트워크 대역폭을 절약 합니다.
- 전송 중 손실 복구: HTTP/2는 데이터 전송 중 발생한 손실을 복구하는 기능을 제공합니다.
- 프레임 버퍼링: HTTP/2는 데이터를 프레임 단위로 전송하여 효율적인 처리를 가능하게 합니다.
gRPC는 C++, Java, Go, Python, Ruby, JavaScript 등 다양한 언어를 지원하며, Linux, Windows, macOS, Android, iOS 등 다양한 플랫폼에서 사용할 수 있습니다.
gRPC는 개발의 용이성을 위해 설계되었습니다.
gRPC는 Protobuf를 사용하여 서비스 인터페이스를 정의할 수 있습니다.
Protobuf는 직관적인 구문과 다양한 언어와 플랫폼에서 사용할 수 있는 라이브러리를 제공하여 개발을 용이하게 합니다.
Restful api & GraphQL & gRPC
gRPC 아키텍처
- gRPC-Web : FrontEnd-Backend 등 모두 gRPC를 사용하는 형태
- 프로토콜 버퍼를 중심으로 통신
- REST api : FrontEnd-Backend간 통신은 Rest Api를 사용하지만 Backend에서는 gRPC를 사용하는 형태
- http로 통신
- 언어중립적인 특징으로 MSA구조에 잘 맞는 아키텍처 구성이 가능 합니다.
- 많은 서비스 간의 api호출로 인한 성능 저하를 개선하며 보안, api gateway, logging 등을 개발하기 쉽습니다.
gRPC Application 개발
서비스 인터페이스 정의
- gRPC 개발 시 가장 먼저 해야할 일은 서비스 인터페이스를 정의 하는 것 입니다.
- 프로토콜 버퍼(protocal buffers)를 IDL(Interface Definition Language)을 사용해 서비스 인터페이스를 정의
ex) SelectService.proto 파일
syntax = "proto3";
import "storage/DataTypes.proto";
option java_multiple_files = true;
package org.emuggie.carabiner.grpc.pact.select;
service SelectService {
rpc select(org.emuggie.carabiner.grpc.pact.data.Query) returns (org.emuggie.carabiner.grpc.pact.data.Nodes);
rpc explainSelect(org.emuggie.carabiner.grpc.pact.data.Query) returns (org.emuggie.carabiner.grpc.pact.data.Message);
rpc getLiteralIndexes(org.emuggie.carabiner.grpc.pact.data.IndexQuery) returns(org.emuggie.carabiner.grpc.pact.data.Indexes);
rpc getEdgeIndexes(org.emuggie.carabiner.grpc.pact.data.IndexQuery) returns(org.emuggie.carabiner.grpc.pact.data.Indexes);
}
서비스 인터페이스 정의가 완료되면 이를 사용해 프로토콜 버퍼 컴파일러인 protoc를 사용해 서버와 클라이언트에 코드를 생성할 수 있다.
- 자바의 경우 메이븐, 그래들 같은 빌드 자동화 도구를 사용할 수 있다.
- 프로토콜 버퍼용 gRPC 플러그인을 사용하면 gRPC의 서버 측과 클라이언트 측 코드 뿐만 아니라 정의된 메시지 타입의 데이터 지정, 직렬화, 데이터 취득의 일반 프로토콜 버퍼 코드를 생성 할 수 있다.
- 즉, protocal buffer가 제공해주는 코드를 재정의 하여 서버는 스켈레톤을 만들고 클라이언트는 스텁 코드를 만든다.
클라이언트-서버 메시지 흐름
- gRPC 클라이언트가 gRPC서비스를 호출할 때 클라이언트의 gRPC라이브러리는 프로토콜 버퍼를 사용해 원격 프로시저 호출 프로토콜 버퍼 형식으로 마샬링하고 http/2를 통해 전송 합니다.
- 서버측에서는 요청을 언마샬링하고 각 프로시저 호출은 프로토콜 버퍼에 의해 실행 합니다.
gRPC 통신 패턴
- 단순 RPC(단일 RPC) : 말 그대로 단일요청(Request) 단일응답(Response)
- Server 스트리밍 RPC : 서버가 클라이언트의 요청 메시지를 받은 후 일련의 응답을 다시 보냅니다.
- 모든 서버 응답을 보낸 후 서버는 서버의 상태 정보를 후행 메타데이터로 클라이언트에 전송해 스트림의 끝을 알려줍니다.
- Client 스트리밍 RPC : 클라이언트가 하나의 요청이 아닌 여러 메시지를 서버로 보내고, 서버는 클라이언트에게 단일 응답을 보냅니다.
- 서버는 클라이언트에서 모든 메시지를 수신해 응답을 보낼 때까지 기다릴 필요는 없습니다.
- 로직에 따라 스트림에서 하나 또는 여러 개의 메시지를 읽은 후 또는 모든 메시지를 읽은 후 응답을 보낼 수 있습니다.
- 양방향 스트리밍 RPC : 클라이언트는 메시지 스트림으로 서버에 요청을 보내고, 서버는 메시지 스트림으로도 응답 합니다.
gRPC 고급기능
- 인터셉터
-
- 클라이언트나 서버에 원격 함수 실행 전후 몇가지 공통적인 로직을 실행할 필요가 있을때 사용 합니다.
- 보통 로깅, 인증, 메트릭등을 구현할 때 사용 합니다.
- 데드라인
- 데드라인과 타임아웃은 분산 컴퓨팅에서 일반적으로 사용되는 패턴 입니다.
- 타임아웃은 클라이언트 app가 RPC가 완료 될 때까지 에러로 종료되기 전 얼마의 시간동안 기다릴지를 지정 합니다.
- 데드라인은 복잡하게 얽힌 서비스 즉, 하나의 요청이 하나 이상의 서비스를 호출 할 때 각 서비스 호출마다 개별 RPC기준으로 타임아웃을 적용할 수도 있지만
- 요청 전체 수명주기에는 직접 적용할 수 없습니다. 이런 경우에는 데드라인을 사용해야 합니다.
- 데드라인을 사용하지 않고 클라이언트 애플리케이션을 개발하면 시작된 RPC 요청에 대한 응답을 무한정 기다리며, 모든 진행 중인 요청에 대해 리소스가 계속 유지 됩니다.
- 이로 인해 서비스는 물론 클라이언트도 리소스가 부족해져 서비스 대기 시간이 길어지게 되며, 결국 전체 gRPC 서비스가 중단 될 수 있습니다.
- 취소처리
- 클라이언트와 서버 애플리케이션 사이의 gRPC 연결에서 이들 모두 성공여부를 독립적이고 개별적으로 결정 합니다.
- 에를들어 서버에서는 성공적으로 끝났지만 클라이언트에서는 실패하는 RPC가 있을수 있습니다.
- 이럴 때 클라이언트나 서버 애플리케이션은 RPC 중단을 시키려고 할 때 RPC 취소를 하면 됩니다.
- 취소가 되면 더이상 RPC관련 메시징을 처리 할 수 없고 RPC를 취소했다는 사실이 전파 됩니다.
- 에러처리
- gRPC를 호출하면 클라이언트는 성공 상태의 응답을 받거나 에러 상태를 갖는 에러를 받습니다.
- 클라이언트 애플리케이션은 발생 가능한 모든 에러와 에러상태를 처리하는 방식으로 작성해야 합니다.
- 서버 애플리케이션도 에러를 처리하고 해당 상태 코드로 적절한 에러를 생성해야 합니다.
- 즉, 에러가 발생하면 에러상태의 자세한 정보를 제공하는 에러메시지와 함께 에러상태 코드를 반환 해야합니다.
- 멀티플렉싱
- gRPC를 사용하면 동일한 RPC서버에서 여러 gRPC 서비스를 실행할 수 있습니다 클라이언트도 마찬가지입니다.
- 동일한 gRPC 클라이언트가 여러 gRPC 스텁에 연결하여 사용할 수 있습니다.
- 이런 기능을 멀티플렉싱이라고 합니다.
- 메타데이터
- gRPC 애플리케이션은 일반적으로 gRPC 서비스와 소비자 사이의 RPC호출을 통해 정보를 공유한다.
- 대부분 서비스 비즈니스 로직과 직접관련 된 정보는 원격 메소드 호출 인자의 일부 입니다.
- 그러나 특정조건에서 RPC비즈니스 로직과 관련이 없는 RPC호출 정보를 공유할 수 있는데 RPC 인자의 일부가 돼서는 안됩니다.
- 이런 경우 gRPC 서비스나 gRPC 클라이언트에서 보내거나 받을 수 있는 gRPC 메타 데이터를 사용할 수 있습니다.
- 보통 gRPC 애플리케이션간에 보안 헤더를 교환할 때 사용됩니다.
예제 소스는 아래와 같습니다.
gRPC proto buf : https://github.com/pthahaha/AppArchiGuideGrpcProtoBuf
server : https://github.com/pthahaha/ApplicationArchitectureGuide-grpcServer
client : https://github.com/pthahaha/ApplicationArchitectureguide
참고 : 아래의 책을 스터디 하면서 작성:)