gRPC server 만들기

Divan·2022년 12월 15일
4
post-thumbnail
post-custom-banner

full source link

MSA에서 rest api 대신 grpc를 사용하여 통신이 가능하다. 더 빠르다고 하나, 엄청난 속도 차이(몇 ms 차이)가 나지는 않는다. Proctocall에 대한 정의가 더욱 분명하여 통신 실수가 줄어든다.

grpc를 테스트 하기 위해서 아래와 같은 순서로 진행 하겠습니다.
goProject 생성 -> .proto파일 생성 -> proto파일 컴파일 -> Server에 컴파일된 proto 파일 import -> bloomrpc로 호출 (client역활)


1. proto 파일 생성

먼저 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 하는것이 효율적입니다.


2. proto 파일 빌드

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}를 변경
protopath
예제(나의경우)

$ 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 파일이 생성된것을 확인 가능하다.
after compile


3. Server에 컴파일된 proto 파일 import

편의를 위해서 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를 호출하면 된다.
실행


4. bloomrpc로 호출 (client역활)

서버를 제작시에 매번 클라이언트를 코드로 생성할 수 없다. 그렇기에 call을 위한 툴로 bloomrpc를 사용하여 테스트한다.

Install

  • for Mac
brew install --cask bloomrpc
  • for windows
choco install bloomrpc

-- 참고 --
아래의 경우 mac의 경우 보안을 해제해야한다.

시스템 설정 -> 개인정보보안
보안

  • 버튼을 클릭 -> book.proto파일을 등록

등록된 화면

GetBook을 클릭
Env의 port를 9000으로 변경 -> id를 1로 입력 -> 재생버튼 클릭 -> 우리가 data.go의 map으로 등록한 정보를 확인


ps. Clinet부분을 포스트 예정_

profile
하루 25분의 투자
post-custom-banner

0개의 댓글