Como invocar com gRPC

Nesta página, mostramos detalhes específicos de exibição do Knative para desenvolvedores que querem usar o gRPC para conectar um serviço de exibição do Knative a outros serviços, por exemplo, para fornecer comunicação simples e de alto desempenho entre microsserviços internos. A disponibilização do Knative é compatível com chamadas gRPC unárias e streaming.

gRPC unária

Em uma chamada RPC unária, o cliente envia uma única solicitação ao servidor e recebe uma única resposta, semelhante a uma chamada de função normal:
rpc SayHello(HelloRequest) returns (HelloResponse);

gRPC Streaming

As opções de streaming a seguir estão disponíveis com o gRPC. RPCs de streaming de servidor em que o cliente envia uma solicitação ao servidor e recebe um stream de leitura contendo uma sequência de mensagens. O cliente lê o stream retornado até que não haja mais mensagens.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

RPCs de streaming de servidor em que o cliente grava uma sequência de mensagens e as envia ao servidor em um stream. Depois que o cliente terminar de gravar as mensagens, ele aguardará a resposta do servidor.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

RPCs de streaming bidirecional em que o cliente e o servidor enviam mensagens em dois fluxos de leitura/gravação que operam de forma independente.

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

Os possíveis casos de uso são estes:

  • Comunicação entre microsserviços internos.
  • Altas cargas de dados (o gRPC usa buffers de protocolo (em inglês), que são até sete vezes mais rápidos do que as chamadas REST).
  • Basta uma única definição de serviço simples. Não é necessário escrever uma biblioteca de cliente completa.

Para integrar seu serviço ao gRPC:

  • Defina as mensagens de solicitação e as respostas em um arquivo proto e compile-as.
  • Crie um servidor gRPC para processar solicitações e retornar respostas: ele precisa detectar a variável de ambiente PORT.
  • Crie um cliente que envie solicitações e processe respostas do servidor gRPC.
  • Como opção, adicione uma autenticação.
  • Crie e implante seu serviço.

Como definir e compilar mensagens em um arquivo proto

Não há itens específicos ou extras ou que servem o Knative para adicionar às definições de proto. Assim como qualquer outro uso do gRPC, você usa buffers de protocolo gRPC para definições de serviço e serialização de dados.

Como criar um cliente gRPC

Não há itens extras ou específicos que disponibilizem o Knative a serem adicionados a um cliente que usa o gRPC. Siga os documentos do gRPC sobre como usar definições de serviço no código do cliente e os clientes de exemplo fornecidos nos tutoriais do gRPC específicos da linguagem.

Como detectar solicitações gRPC em um serviço de exibição Knative

O único requisito especial para um servidor gRPC em execução na disponibilização Knative é detectar na porta especificada pela variável de ambiente PORT, conforme mostrado no código:

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)
	}
}

Como abrir uma conexão gRPC com um serviço

Para abrir uma conexão gRPC com um serviço para enviar mensagens gRPC, é necessário especificar o domínio do host, que é o URL do serviço de exibição Knative ou o domínio personalizado mapeado para esse serviço, junto com a porta 443, que é a porta esperada para ser usada pelo gRPC.

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...)
}

Como enviar solicitações gRPC sem autenticação

No exemplo a seguir, mostramos como enviar uma solicitação sem autenticação, usando uma conexão gRPC configurada conforme mencionado anteriormente.

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)
}