MSA에서 rest api 대신 grpc를 사용하여 통신이 가능하다. 더 빠르다고 하나, 엄청난 속도 차이(몇 ms 차이)가 나지는 않는다. Proctocall에 대한 정의가 더욱 분명하여 통신 실수가 줄어든다.
grpc를 테스트 하기 위해서 아래와 같은 순서로 진행 하겠습니다.
goProject 생성 -> .proto파일 생성 -> proto파일 컴파일 -> Server에 컴파일된 proto 파일 import -> bloomrpc로 호출 (client역활)
먼저 go mod init으로 프로젝트를 생성합니다. 프로젝트 폴더 내에 생성하지 않아도 되지만 편의상 프로젝트 폴더 내에 proto폴더를 생성합니다.
goProject생성 -> proto/v1 폴더 생성 -> book.proto파일을 생성.
syntax = "proto3";// gRPC syntaxe 버전
package v1.book;
option go_package = "github.com/SeoEunkyo/gRPC-golang/protos/v1/book";
// Book이라는 서비스를 정의 현재는 Get만 정의, 추후 입력 추가
service Book {
rpc GetBook(GetBookRequest) returns (GetBookResponse);
}
// 메세지형태를 정의
// reserved는 해당수는 여기서 3~4는 추후에 사용하겠다
message BookMessage {
reserved 3 to 4;
int32 id = 1;
string title = 2;
string Description =5;
string writer = 6;
}
// 입력받을 파라미터를 정의 -> id를 받아서 해당하는 정보를 조회 해서 리턴
message GetBookRequest {
int32 id = 1;
}
// 응답시에 보내게될 정보
// repeated 는 "배열형태로 응답하겠다" 라는 의미
message GetBookResponse {
BookMessage book_message = 1;
}
*참고
Field numbers의 값이 1~15 사이면 1 byte로 encoding 됩니다.
Field numbers의 값이 16~2047이면 2 bytes로 encoding 됩니다.
그렇기에 Field numbers의 값을 1~15 사이로 encoding 하는것이 효율적입니다.
gPRC Quick Start를 참고하여 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
환경변수 설정
$ export PATH="$PATH:$(go env GOPATH)/bin"
Proto파일 컴파일
$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
{Proto 파일 Path}
아래 경로를 참고하여 {Proto 파일 Path}를 변경
예제(나의경우)
$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
protos/v1/book.proto
컴파일 이후에 book.pd.go와 book_grpc.pd.go 파일이 생성된것을 확인 가능하다.
편의를 위해서 server 디렉토리를 생성하고 main.go를 생성하세요.
server디렉토리 아래 data디렉토리를 생성하고 book.go파일을 생성합니다. map을 하나 생성합니다. 보통은 DB에서 조회해서 데이터를 리턴하지만 여기서는 map으로 대처합니다.
// server/data/book.go
package data
import bookpd "github.com/SeoEunkyo/gRPC-golang/protos/v1"
var BookData = map[int32]*bookpd.BookMessage{
1: {
Id: 1,
Title: "book1",
Writer: "Henry",
Description: "01012341234",
},
2: {
Id: 2,
Title: "book2",
Writer: "new jin",
Description: "make cookie",
},
3: {
Id: 3,
Title: "book3",
Writer: "grammy",
Description: "hi Grammy",
},
}
이전에 book.proto에서 rpc로 등록하였는 GetBook 함수를 정의합니다.
그리고 grpc서버에 등록한다.
//server/main.go
package main
import (
"context"
bookpd "github.com/SeoEunkyo/gRPC-golang/protos/v1"
"github.com/SeoEunkyo/gRPC-golang/server/data"
"google.golang.org/grpc"
"log"
"net"
)
const portNumber = "9000"
type bookServer struct {
bookpd.BookServer
}
func (s *bookServer) GetBook(ctx context.Context, req *bookpd.GetBookRequest) (*bookpd.GetBookResponse, error) {
bookId := req.Id
var bookMessage *bookpd.BookMessage
bookMessage = data.BookData[bookId]
return &bookpd.GetBookResponse{
BookMessage: bookMessage,
}, nil
}
func main() {
lis, err := net.Listen("tcp", ":"+portNumber)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
//grpc서버에 등록하기.
grpcServer := grpc.NewServer()
bookpd.RegisterBookServer(grpcServer, &bookServer{})
log.Printf("start gRPC server on %s port", portNumber)
if err := grpcServer.Serve(lis); err != nil {
log.Fatalf("failed to serve: %s", err)
}
}
아래와 같이 9000번 포트로 실행이 된것을 확인한다. 이제 준비가 완료, client에서 rpc를 호출하면 된다.
서버를 제작시에 매번 클라이언트를 코드로 생성할 수 없다. 그렇기에 call을 위한 툴로 bloomrpc를 사용하여 테스트한다.
Install
brew install --cask bloomrpc
choco install bloomrpc
-- 참고 --
아래의 경우 mac의 경우 보안을 해제해야한다.
시스템 설정 -> 개인정보보안
등록된 화면
GetBook을 클릭
Env의 port를 9000으로 변경 -> id를 1로 입력 -> 재생버튼 클릭 -> 우리가 data.go의 map으로 등록한 정보를 확인
ps. Clinet부분을 포스트 예정_