Post

RPC 알아보기 1 - RPC란

Intro

서비스가 거대해짐에 따라 Monolithic 아키텍처는 유지 보수하기 힘들어졌다. 빌드와 배포 시간이 길어지고 에러가 전파될 수 있으며 코드의 양이 많아졌다. 그래서 마이크로서비스 아키텍처가 (대)기업에서 많이 채택되는 추세인가 보다.
MSA에 중요한 요점 중 하나는 서버간 통신이다. 각 서버는 다른 언어로 작성될 수 있다. 다른 플랫폼을 가진 프로세스끼리 통신하기 위해 HTTP, RPC, MOM(Message-oriented)을 사용한다.
MSA를 학습하기 위한 첫 단계로 RPC에 대해 정리하고자 한다. 특히 분산 시스템(distributed-system) 관점에서 정리한다.

RPC는 전반적인 통신 기술을 의미한다. 구체적인 구현체에 따라 CORBA, gRPC(Google), Thrift(Meta)가 존재한다.

Motivation

분산 시스템의 중요한 키워드는 transparency 이다. 특히 application 레이어를 개발하는 개발자 입장에서 access transparency를 만들어주기 위해 미들웨어를 사용한다. 개발자는 하나의 로컬 컴퓨터에서 프로세싱이 일어나는건지, 외부 컴퓨터에서 프로세싱이 일어나는건지를 구분할 수 없어야 한다.

하지만 누군가는 외부와 통신하는 주체가 있어야한다. 그 주체를 미들웨어에 맡기자는게 핵심이다. Middleware에서는 외부 서버와 통신하는 과정이 있지만, application layer 측면에서는 숨기고자 한다. RPC는 그 방법 중 하나로 로컬 프로시저를 실행하는 것처럼 외부 프로시저를 사용하는 방법이다.

Client, Server stubs

요청(request)하는 서버를 Client, 요청 받는 서버를 Server 라고 하자.
RPC에서는 middleware를 stub 이라고 부른다. 클라이언트의 application layer에서 특정 프로시저를 실행하면, 그 하위 레이어인 client stub이 요청을 받는다. client stub은 적절하게 프로시저 이름, 파라미터 value 등을 변환 후 server stub에게 전달한다. 이때 변환하는 규칙을 지정한 언어를 IDL(Interface Definition Language) 라고 한다.

https://co-no.tistory.com/entry/통신-RPCRemote-Procedure-Call의-개념-및-특징

이때 변환하는 과정을 marshalling, unmarshalling 이라고 한다. RPC의 구현체에 따라 그 과정이 상이하다. 왜 메시지 변환 과정이 필요한지 살펴보자

Passing value parameters

통신하는 기기는 서로 플랫폼이 다를 수 있다. 즉, heterogeneous machines들의 통신이다.
같은 숫자나 문자라도 표현하는 방식이 다를 수 있다. 음수나 floating-point를 나타내는 방식이 다를 수 있다. 바이트 저장 순서에 따라 little endian, big endian이 다를 수 있다.
따라서 메시지 송수신을 위해서는 특정한 약속(프로토콜)이 필요한거다.

또 다른 이슈가 있다. 파라미터 전달 방식에는 call-by-value와 call-by-reference가 있다. 문제가 되는 부분은 call-by-reference이다.
변수에 메모리 주소를 저장하게 되는데, 이 주소는 client에서만 의미있는 주소다. 이를 해결하기 위해 call-by-copy/restore를 사용한다.
쉽게 말하면 실제 데이터로 변환해서 메시지를 만든다. 파라미터 메시지에 주소 값이 아니라, 실제 데이터를 넣어서 호출한다. reply로 온 값을 메모리 상에 그대로 복사한다.

Synchronous, Asynchronous

기본적으로 RPC는 transient + synchronization 이다.

  • transient: 클라이언트가 프로시저를 호출할 때 서버는 정상 작동 중이어야 한다.
  • synchronization: 서버의 reply가 올 때까지 클라이언트는 다음 라인을 실행하지 않는다.

하지만 구현 방법마다 달라진다. 대표적으로 gRPC는 Asynchronous를 지원한다.

(b)server application layer의 실행과 동기화하지 않는다는 관점에서 Asynchronous이다.

위 이미지(b)에 의문을 가질 수 있다. Client가 잠깐 응답을 기다리는 타임이 있는데.. 이거 synchronization 아닌가?
비동기라도 여러 방식이 존재한다. 클라이언트는 reply 자체를 기다리지 않고 계속 실행할 수도 있다(One-way RPC). 속도는 더 빠를 수 있지만, 네트워크 reliability가 보장되지 않는 환경에서는 최소한 server의 stub 응답 정도는 받는게 안전할 것 같다.

서버가 프로시저를 실행하는 동안 기다리기는 싫지만, 결과물은 받고 싶을 때에는 deferred synchronous RPC를 사용하기도 한다.

This post is licensed under CC BY 4.0 by the author.