-
RPC (Remote Procedure Call) 알아보기System 2023. 10. 14. 11:24728x90반응형
- 목차
소개.
RPC 는 Remote Procedure Call 의 약자입니다.
의미는 "원격 서버에 있는 함수를 사용한다" 라는 뜻인데요.
프로그래밍에서 함수를 뜻하는 여러 표현들이 있습니다.
Function, Procedure, Method 등은 제각각 고유의 목적이 있어서 약간의 차이는 존재하지만,
이번 글에선 다 같은 함수라고 생각하겠습니다.
어떤 프로그램이 하나 존재한다고 했을 때,
이 프로그램이 프로그램 내부에 선언된 함수들을 사용할 수 있습니다.
하지만 이 프로그램이 그 함수를 가지고 있지 않다면,
다른 곳에 있는 함수를 사용해야할 상황이 생길 수 있겠죠.
RPC 는 이러한 상황을 커버하기 위해서 만들어진 Procedure Call 방식입니다.
이어지는 내용에서 자세히 알아보도록 하겠습니다.
라이브러리와 차이가 뭘까?
보통 Dependency, Module, Library 라고 칭하는 외부 모듈들이 있습니다.
Python 이라면 numpy, pandas, pytorch 등의 모듈을 requirements.txt 에 넣어서 사용하죠.
해당 외부 모듈들이 Python 환경으로 받아져서 내부에서 사용할 수 있게 됩니다.
즉, 외부 통신이 아닌거죠.
Javascript 도 expressjs, D3js 등의 외부 라이브러리를 내부로 설치하여 사용합니다.
RPC 는 이런 라이브러리들과 달리 프로그램 내부에 설치하여 사용하지 않습니다.
Client 에서 해당 함수를 호출하면 내부적으로 Server 의 함수를 호출하고 그 결과를 Client 로 반환합니다.
이 과정에서 필연적으로 네트워크 통신이 사용되며, 네트워크 통신을 철저히 감추어집니다.
Network 관점에서 RPC.
RPC 는 결국에는 Client 와 Server 사이의 네트워크 통신입니다.
일반적인 HTTP 프로토콜 통신과 여러 다른 RPC 통신에 대해서 알아보겠습니다.
HTTP 프로토콜로 연결된 Client-Server.
간단한 코드로 예시를 들어보겠습니다.
아래 코드는 RPC 를 http 프로토콜로 구현한 내용입니다.
<Client>import requests def add(numA, numB): # Send a POST request to the `/api/users` endpoint with the JSON body. response = requests.get(f'http://localhost:8888/add?numA={numA}&numB={numB}') # If the request was successful, print the response body. if response.status_code == 200: return response.content.decode("utf8") else: # An error occurred. print(response.status_code, response.reason) result = add(10, 2)
<Server>
import http.server import re class HTTPServer(http.server.SimpleHTTPRequestHandler): def do_GET(self): # Handle the GET request. self.send_response(200) self.send_header('Content-type', 'application/json') rawNumA, rawNumB = self.path.split("?")[1].split("&") numA = re.sub("[^\d]", '', rawNumA) numB = re.sub("[^\d]", '', rawNumB) result = int(numA) + int(numB) self.end_headers() # Write the response body. self.wfile.write(f"{result}".encode("utf8")) if __name__ == '__main__': server = http.server.HTTPServer(('localhost', 8888), HTTPServer) server.serve_forever()
RPyC 로 연결한 Client 와 Server.
python 의 대표적인 RPC 모듈인 RPyC 로 구현한 RPC 통신의 예시입니다.
RPC 서버의 add 함수를 Client 에서 사용합니다.
1 과 2를 더해 3 이라는 결과를 얻을 수 있습니다.
<RPyC Client>import rpyc # Create a RPC client. client = rpyc.connect('localhost', 18812) # Call the remote procedure on the RPC server. result = client.root.add(1, 2) # Print the result. print(result)
<RPyC Server>import rpyc from rpyc.utils.server import ThreadedServer class MyService(rpyc.Service): # My service def exposed_add(self, a, b): return a + b if __name__ == "__main__": server = ThreadedServer(MyService, port = 18812) server.start()
<실행 결과>3
그래서 Network 통신과 RPC 의 차이가 뭐니?
RPC 또한 내부적으로 Network 통신을 사용합니다.
그래서 이럴거면 그냥 "HTTP 프로토콜을 사용해서 API 를 호출해서 쓰면 되는거 아니야?" 라고 생각할 수 있습니다.
그래서 RPC 가 무엇인가에 대해서 상세히 적어보려고 합니다.
1. RPC 는 Remote Procedure Call 의 방법론일 뿐입니다.
RPC 는 네트워크 통신을 통한 원격 서버의 함수를 사용하는 방법론입니다.
이를 구체화시킨 것이
RPyC, JSON-RPC, gRPC 등등이 있습니다.
( 다음 글에선 gRPC 에 대해서 자세히 알아보는 시간을 가질 예정입니다. )
HTTP 프로토콜을 쓰든 안쓰든,
Client 가 호출하는 Server 의 함수가 실제로 존재하든 하지 않든,
Client 가 요청하는 요구 사항을 Server 가 처리해주는 네트워크적인 관계가 성립이 된다면
모두 RPC 라고 Rough 하게 인식해도 된다고 생각합니다.
이를 구체적으로 구현한 것이 위의 종류들입니다. (RPyC, JSON-RPC, gRPC)
2. RPC 를 위한 네트워크 프로토콜이 명료하게 지정된 것이 아닙니다.
gRPC 는 gRPC 만의 7-layer 의 프로토콜이 존재합니다만,
RPC 자체는 약속된 프로토콜 체계는 없습니다.
그저 TCP 레이어 위에서 client 와 server 가 통신할 수 있으면 됩니다.
RPyC 의 경우에도 이들이 사용하는 application-layer 의 프로토콜이 정해져 있지 않습니다.
그러니깐 HTTP , FTP, jdbc 같이 이름지어져 있지 않습니다.
RPyC 클라이언트와 RPyC 서버 간의 약속된 방식으로
- 데이터를 인코딩/디코딩하고
- 압축을 하거나 풀며
- 데이터를 파싱합니다.
만약 RPyC Client 가 javascript 베이스인 jsonrpc 모듈은 구현한 Server 와 쉽게 통신할 수 없습니다.
즉, 여러 RPC 방식들이 프로그래밍 언어와 시스템 환경에 의존적입니다.
약속된 프로토콜이 아니므로 general 하게 사용할 수 없습니다.
(다만, gRPC 는 이러한 문제와 달리 하나의 Protocol 입니다 !)
만약 Client-Server 의 통신을 general 하게 사용하고 싶다면,
HTTP 나 여타 프로토콜을 사용하시면 됩니다.
대신 RPC 를 사용함으로써 정말 필요한 정보만으로 간결하게 통신할 수 있는 장점도 있습니다.
정리하면.
RPC 는 클라이언트와 서버 사이의 소통을 위한 방법론입니다.
일반적인 HTTP 를 활용한 API Server 도 RPC 가 될 수 있다고 생각합니다.
하지만 RPC 는 느낌적으로
- Client 가 Server 의 상태를 체크하는 함수를 호출하거나
- Client 가 자신의 리소스로 감당할 수 없는 무거운 연산 수행을 서버에게 맡긴다거나
이런 느낌으로 Server 만이 처리할 수 있는 작업을 요청하는 느낌이 강합니다.
예를 들어,
아래와 같은 느낌의 Procedure 들을 Client 가 원격에서 호출하는 것이죠. (Remote Procedure Call)
function compute_heavy() { // .... // .... // 엄청 많은 양의 연산이 수행됨. } function check_status() { // 서버의 cpu, memory, network 등의 리소스 사용량을 전달함. }
반응형'System' 카테고리의 다른 글
Standard Input (표준입력) 이해하기 (0) 2023.10.16 IPC Signal 알아보기 (0) 2023.10.07 Shared memory communication 알아보기 (0) 2023.10.07 [memory management] page 알아보기 (0) 2023.09.22 Call Stack 이해하기 (0) 2023.09.21