[Golang + gRPC] gRPC를 사용하기 위해 필요한 패키지 정리

2022. 2. 4. 19:45Dev/Golang

* 기본적인 gRPC

go get google.golang.org/grpc

 

* gRPC 요청 테스트를 위해(grpcurl, bloomrpc 등) 모든 gRPC를 등록하기 위한 리플렉션

google.golang.org/grpc/reflection

 

* gRPC 요청에서 처리할 미들웨어 (캐싱, 유저 인증 등의 인터셉터)

go get github.com/grpc-ecosystem/go-grpc-middleware			
go get github.com/grpc-ecosystem/go-grpc-middleware/auth 	
go get github.com/grpc-ecosystem/go-grpc-middleware/loggin/logus	
go get github.com/grpc-ecosystem/go-grpc-middleware/recovery

-> 각 순서대로 미들웨어, 유저 인증 관련, logging 관련, recovery(panic 발생했을 때 서버가 죽지 않게 복원해줌) 관련 미들웨어

자세한 내용은 아래 링크를 참조

https://github.com/grpc-ecosystem/go-grpc-middleware

 

GitHub - grpc-ecosystem/go-grpc-middleware: Golang gRPC Middlewares: interceptor chaining, auth, logging, retries and more.

Golang gRPC Middlewares: interceptor chaining, auth, logging, retries and more. - GitHub - grpc-ecosystem/go-grpc-middleware: Golang gRPC Middlewares: interceptor chaining, auth, logging, retries a...

github.com

 

-> middleware는 unary, streaming 모두 따로 등록을 해줘야 함

=>간단한 middleware 사용법

package router

import (
	"context"
	"log"
	"net"

	"github.com/sirupsen/logrus"

	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
	grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
	grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

const (
	port = ":9000"
)

//유저 인증 JWT 토큰 Interceptor : token값을 decode하여 memId를 전달
func authInterceptor(ctx context.Context) (context.Context, error) {

	token, _ := grpc_auth.AuthFromMD(ctx, "bearer")
	if len(token) == 0 {
		newCtx := context.WithValue(ctx, "memId", "")
		return newCtx, nil
	}

	memId, err := jwtUtil.ValidateToken(token)

	newCtx := context.WithValue(ctx, "memId", memId)
	return newCtx, err
}

//cache를 위한 custom unary interceptor
func customCacheUnaryInterceptor() grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
		//handler를 통해 service가 처리된다!!
        res, err := handler(ctx, req)
		return res, err
	}
}

//cache custom streaming interceptor
func customCacheStreamInterceptor() grpc.StreamServerInterceptor {
	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
		return handler(srv, ss)
	}
}

func SetupRouter() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalln("Failed to Listen :", err)
	}

	//log를 확인하기 위한 logrus
	logrus.ErrorKey = "grpc.error"
	logrusEntry := logrus.NewEntry(logrus.StandardLogger())

	s := grpc.NewServer(
		//unary server interceptor middleware
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
			//auth interceptor
			grpc_auth.UnaryServerInterceptor(authInterceptor),

			//logging interceptor
			grpc_logrus.UnaryServerInterceptor(logrusEntry),

			//recovery interceptor : panic 발생해도 프로그램 종료 안됨
			grpc_recovery.UnaryServerInterceptor(),

			//cache interceptor : custom
			customCacheUnaryInterceptor(),
		)),

		//streaming server interceptor middleware
		grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
			//auth_interceptor
			grpc_auth.StreamServerInterceptor(authInterceptor),

			//loggin_interceptor
			grpc_logrus.StreamServerInterceptor(logrusEntry),

			//recovery interceptor
			grpc_recovery.StreamServerInterceptor(),

			//cache interceptor : custom
			customCacheStreamInterceptor(),
		)),
	)
    
	reflection.Register(s)

	log.Printf("Start gRPC Server on %s server", port)
	if err := s.Serve(lis); err != nil {
		log.Fatalln("Failed to Open gRPC Server :", err)
	}
}

'Dev > Golang' 카테고리의 다른 글

[protoc 세팅] MAC protoc-gen-go 설정  (0) 2022.02.08
[Golang] Go Routine 정리  (0) 2022.01.26