구글에서 개발한 RPC 플랫폼
protocol buffer와 RPC를 사용한다.
SSL/TLS를 사용하여 암호화하며, HTTP2.0을 사용한다.
서버의 함수를 클라이언트에서 호출할 수 있어 MSA를 쉽게 구현할 수 있다.
대부분의 언어를 지원하여 언어가 다른 서버간의 통신을 쉽게 구현할 수 있다.
먼저, 서버와 클라이언트에서 동일한 proto를 정의해야 한다.
이번 예시로는 서버간의 연결을 확인해 주는 Connect함수를 정의했다.
sound.proto
syntax = "proto3";
package sound;
option go_package="sound/sound";
service File{
rpc Connect (Ping) returns (Pong);
}
message Ping{
string ping=1;
}
message Pong{
string pong=1;
}
이제 터미널을 이용하여 proto 관련 프로그램을 설치해 주도록 하자.
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
protoc --go_out=. --go-grpc_out=. ./sound/sound.proto
공식 docs에서는
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./sound/sound.proto
의 명령어를 사용하라고 했지만, --go_opt와 --go-grpc_opt 를 인식하지 못하여 빼고 한 결과 정상적으로 파일이 생성되었다.
여기까지 잘 따라오면 sound_grpc.pb.go
와 sound.pb.go
가 생성되었을 것이다.
이제
package grpc
import (
"context"
"log"
pb "solution/grpc/sound/sound"
"time"
"google.golang.org/grpc"
)
func Ping() {
//연결되는 서버 정의
conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
//client 생성
c := pb.NewFileClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
//Ping 전송
r, err := c.Connect(ctx, &pb.Ping{Ping: "Ping!"})
if err != nil {
log.Fatalf("could not request: %v", err)
}
log.Printf("Config: %v", r)
}
이제 Ping()
의 함수를 실행시키면 localhost:8080의 서버에 grpc연결 요청을 보내고, Connect 함수를 실행시킬 수 있다.
파이썬에서도 proto를 정의해야 한다.
하지만 go에서 한 것과 크게 다르지 않다.
//sound.proto
syntax = "proto3";
package sound;
service File{
rpc Connect (Ping) returns (Pong);
}
message Ping{
string ping=1;
}
message Pong{
string pong=1;
}
이제
python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. ./sound.proto
의 명령어를 터미널에서 동작하면 go의 경우와 마찬가지로 두개의 파일이 생성될 것이다.
sound_pb2_grpc.py
sound_pb2.py
이제 서버에서 이 두 파일을 import하여 사용할 수 있다.
//server.py
from concurrent import futures
import logging
import grpc
#생성된 파일 import
import sound_pb2
import sound_pb2_grpc
#File 클래스 정의, 인자는 Servicer을 붙어야 한다.
class File(sound_pb2_grpc.FileServicer):
#request로 받아 결과를 return해야 한다.
def Connect(self, request, context):
print(request.ping)
return sound_pb2.Pong(pong='%s Pong!' % request.ping)
def serve():
#멀티스레딩 설정
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
sound_pb2_grpc.add_FileServicer_to_server(File(), server)
#8080번 포트로 서버 열기
server.add_insecure_port('[::]:8080')
print("server on port 8080")
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
이러한 방법으로 python server를 만들 수 있으며, python 서버를 연 상태로 go의 코드를 실행시키면 서로 통신하여 Connect 함수를 실행시킬 수 있다.