서버 간, 또는 유저 간에 통신할 때, 저는 보통 REST API 방식을 활용했고 그것밖에 몰랐습니다. 하지만 gRPC라는 툴을 통해 스트리밍에 특화된 서비스의 능률을 높일 수 있다는 소식을 듣게 됐습니다. 여기서는.. streaming 통신까지 다루진 않는데,, gRPC 서버 하나 세우고 거기서 연결된 DB를 처리하도록 해보았습니다..
※ 배포도 잘 돼요! 네트워크, IP 설정만 꼼꼼히 신경쓰면 외부에서도 통신되게 할 수 있습니다!(보안 이슈는 잘 모르겠어요,,)
0. 프로젝트 디렉토리 구조
1. 프로젝트 폴더 생성
mkdir project
cd project
2. 파이썬 가상환경 생성 (전 파이참으로 생성) 및 진입
*적절한 위치에 가상환경 파일을 놓으면 파이참이 알아서 찾아서 진입해줘욤
python -m venv venv
cd venv\Scripts
activate
cd ..\..\project
3. 필요 라이브러리 설치
pip install grpcio
pip install grpcio-tools
pip install psycopg2 <-------- 저는 PostgreSQL을 쓸 거라 얘 깔았습니다~
4. .proto 파일 작성 (gRPC docs 예시 따라도 되고 이거 따라서 해도 됩니다)
syntax = "proto3";
package users;
service Functions {
// Send a user id and get his information
rpc GetInfo (UserRequest) returns (UserReply) {}
}
message UserRequest {
int32 id = 1;
}
message UserReply {
string nickname = 1;
string phone = 2;
}
5. .proto 파일을 바탕으로 gRPC 코드 파일들 생성
python -m grpc_tools.protoc -I protos --python_out=. --pyi_out=. --grpc_python_out=. protos\<proto_filename>
6. gRPC server 파일 작성 <= 얘한테 gRPC 요청을 보내는 거에욤
from concurrent import futures
import logging
import grpc
import users_pb2
import users_pb2_grpc
import psycopg2
db = psycopg2.connect(
host="~~~~",
database="~~~~",
user="~~~~",
password="~~~~"
)
class UserService(users_pb2_grpc.FunctionsServicer):
def GetInfo(self, request, context):
cur = db.cursor()
cur.execute("<YOUR SQL QUOTE>")
output = cur.fetchone()
return users_pb2.UserReply(nickname="~~~~", phone="~~~~")
def serve():
port = '50051'
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
users_pb2_grpc.add_FunctionsServicer_to_server(UserService(), server)
server.add_insecure_port('[::]:' + port)
server.start()
print("Server started, listening on " + port)
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
여기선 .proto에서 선언한 함수들(interface같은 친구들)을 구체화하는 파일입니다. 게다가 request라는 요청을 활용하여 client 측에서 보내는 message 파일(.proto의 UserRequest, MannerRequest)들을 파헤쳐 볼 수 있어요~
serve라는 함수에서 서버를 오픈하는데 저도 서버가 열리는 것만 알고 나머진 잘 모르겠네요 ㅎㅎ;;😬
7. gRPC client 파일 작성
client 파일은 다른 언어로 작성해서 요청 넣어도 원활히 작동 돼요 Python, Ruby 2가지 언어로 써보겠습니다.
from __future__ import print_function
import logging
import grpc
import users_pb2
import users_pb2_grpc
def run():
with grpc.insecure_channel('localhost:50051') as channel:
stub = users_pb2_grpc.FunctionsStub(channel)
response = stub.GetInfo(users_pb2.UserRequest(id="~~~~"))
if __name__ == '__main__':
logging.basicConfig()
run()
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'users_services_pb'
def main
hostname = ARGV.size > 1 ? ARGV[0] : 'localhost:50051'
stub = Users::Functions::Stub.new(hostname, :this_channel_is_insecure)
begin
response = stub.get_info(Users::UserRequest.new(id: "~~~~"))
rescue GRPC::BadStatus => e
abort "ERROR: #{e.message}"
end
end
main
그냥 적당~히 .proto에 명세된 대로 따라가 주면 됩니다. 헷갈리지 않게 request나 reply(response) message잘 네이밍해주면 돼요~😎 너무 헷갈리시면 gPRC docs~(https://grpc.io/docs/languages/)
8. gRPC 통신
먼저 서버를 열고
python <server_file>
각 클라이언트 파일을 돌려주면 됩니다. 포트번호, 호스트 주소 통일해줘야 오류가 안나요!!
python <client_file>
ruby <client_file>
참고 자료
gRPC docs
Documentation
A high-performance, open source universal RPC framework
grpc.io
'대학생활' 카테고리의 다른 글
[Python] 주소 공공데이터 좌표 변환 with Google map (0) | 2023.01.28 |
---|---|
[Ruby] Rails with Devise + MyPage (0) | 2023.01.03 |
[Docker] 도커에 관한 이야기 (0) | 2022.11.26 |
[Ruby] Linux에서 Ruby on Rails 깔아보기.. (0) | 2022.11.09 |
[Linux] Kernel Compiling 새 커널을 입혀보자!! (0) | 2022.11.01 |