gRPC로 호출

이 페이지에서는 gRPC를 사용하여 Knative serving 서비스를 다른 서비스(예: 내부 마이크로서비스 간의 간단하면서 고성능의 통신 제공)와 연결하려는 개발자를 위한 Knative serving 관련 세부정보를 보여줍니다. Knative serving은 단항스트리밍 gRPC 호출을 모두 지원합니다.

gRPC 단항

단항 RPC 호출에서 클라이언트는 서버에 단일 요청을 보내고 일반적인 함수 호출과 유사한 단일 응답을 받습니다.
rpc SayHello(HelloRequest) returns (HelloResponse);

gRPC 스트리밍

gRPC에서 사용할 수 있는 스트리밍 옵션은 다음과 같습니다. 서버 스트리밍 RPC의 경우 클라이언트는 서버에 요청을 보내고 일련의 메시지를 포함하는 읽기에 대한 스트림을 가져옵니다. 클라이언트는 메시지가 더 이상 없을 때까지 반환된 스트림을 읽습니다.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

클라이언트 스트리밍 RPC의 경우 클라이언트는 일련의 메시지를 작성한 후 스트림의 서버에 이를 보냅니다. 클라이언트는 메시지 작성을 완료한 후 서버에서 응답을 반환할 때까지 대기합니다.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

양방향 스트리밍 RPC의 경우 클라이언트와 서버가 독립적으로 작동하는 두 개의 읽기-쓰기 스트림에서 메시지를 보냅니다.

rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

사용 가능한 사용 사례는 다음과 같습니다.

  • 내부 마이크로서비스 간의 통신
  • 대량의 데이터. 이 경우 gRPC는 REST 호출보다 최대 7배 빠른 프로토콜 버퍼를 사용합니다.
  • 간단한 서비스 정의만 필요한 경우에는 전체 클라이언트 라이브러리를 작성하지 않아도 됩니다.

서비스를 gRPC와 통합하려면 다음 안내를 따르세요.

  • proto 파일에서 요청 메시지와 응답을 정의하고 컴파일합니다.
  • 요청을 처리하고 응답을 반환하는 gRPC 서버를 만듭니다. 이 서버는 PORT 환경 변수를 리슨해야 합니다.
  • gRPC 서버에서 요청을 보내고 응답을 처리하는 클라이언트를 만듭니다.
  • 원할 경우 인증을 추가합니다.
  • 서비스를 빌드하고 배포합니다.

proto 파일에서 메시지 정의 및 컴파일

proto 정의에 추가할 추가 항목 또는 Knative serving 관련 항목이 없습니다. 다른 용도로 gRPC를 사용할 때와 마찬가지로 서비스 정의 및 데이터 직렬화에는 gRPC 프로토콜 버퍼를 사용합니다.

gRPC 클라이언트 만들기

gRPC를 사용하는 클라이언트에 추가할 추가 항목 또는 Knative serving 관련 항목이 없습니다. 클라이언트 코드의 서비스 정의 사용에 관한 gRPC 문서 및 언어별 gRPC 튜토리얼에 제공된 샘플 클라이언트를 따르세요.

Knative serving 서비스에서 gRPC 요청 리슨

Knative serving에서 실행 중인 gRPC 서버에 적용되는 특별한 요구사항은 단 한 가지인데, 이는 다음 코드에 표시된 바와 같이 PORT 환경 변수로 지정된 포트를 리슨해야 한다는 것입니다.

Go

func main() {
	log.Printf("grpc-ping: starting server...")

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		log.Printf("Defaulting to port %s", port)
	}

	listener, err := net.Listen("tcp", ":"+port)
	if err != nil {
		log.Fatalf("net.Listen: %v", err)
	}

	grpcServer := grpc.NewServer()
	pb.RegisterPingServiceServer(grpcServer, &pingService{})
	if err = grpcServer.Serve(listener); err != nil {
		log.Fatal(err)
	}
}

서비스에 대한 gRPC 연결 열기

서비스에 대한 gRPC 연결을 열어 gRPC 메시지를 보내려면 Knative serving 서비스의 URL 또는 해당 서비스에 매핑된 커스텀 도메인인 호스트 도메인을 gRPC에서 사용할 것으로 예상되는 포트 443과 함께 지정해야 합니다.

Go


import (
	"crypto/tls"
	"crypto/x509"

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

// NewConn creates a new gRPC connection.
// host should be of the form domain:port, e.g., example.com:443
func NewConn(host string, insecure bool) (*grpc.ClientConn, error) {
	var opts []grpc.DialOption
	if host != "" {
		opts = append(opts, grpc.WithAuthority(host))
	}

	if insecure {
		opts = append(opts, grpc.WithInsecure())
	} else {
		// Note: On the Windows platform, use of x509.SystemCertPool() requires
		// go version 1.18 or higher.
		systemRoots, err := x509.SystemCertPool()
		if err != nil {
			return nil, err
		}
		cred := credentials.NewTLS(&tls.Config{
			RootCAs: systemRoots,
		})
		opts = append(opts, grpc.WithTransportCredentials(cred))
	}

	return grpc.Dial(host, opts...)
}

인증 없이 gRPC 요청 전송

다음 샘플은 앞서 설명한 대로 구성된 gRPC 연결을 사용하여 인증 없이 요청을 보내는 방법을 보여줍니다.

Go


import (
	"context"
	"time"

	pb "github.com/GoogleCloudPlatform/golang-samples/run/grpc-ping/pkg/api/v1"
	"google.golang.org/grpc"
)

// pingRequest sends a new gRPC ping request to the server configured in the connection.
func pingRequest(conn *grpc.ClientConn, p *pb.Request) (*pb.Response, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client := pb.NewPingServiceClient(conn)
	return client.Send(ctx, p)
}