Invocar com gRPC

Esta página mostra detalhes específicos do Knative Serving para programadores que querem usar o gRPC para ligar um serviço do Knative Serving a outros serviços, por exemplo, para fornecer uma comunicação simples e de alto desempenho entre microsserviços internos. O Knative serving suporta chamadas gRPC unárias e de streaming.

gRPC Unário

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

Streaming gRPC

As seguintes opções de streaming estão disponíveis com o gRPC. RPCs de streaming do servidor em que o cliente envia um pedido para o servidor e recebe um fluxo para ler que contém uma sequência de mensagens. O cliente lê o fluxo devolvido até não existirem mais mensagens.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

RPCs de streaming do cliente em que o cliente escreve uma sequência de mensagens e envia-as para o servidor num fluxo. Depois de o cliente terminar de escrever mensagens, aguarda que o servidor devolva a respetiva resposta.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

RPCs de streaming bidirecional em que o cliente e o servidor enviam mensagens em dois streams de leitura/escrita que funcionam de forma independente.

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

Seguem-se alguns exemplos de utilização:

  • Comunicação entre microserviços internos.
  • Cargas elevadas de dados (o gRPC usa buffers de protocolo, que são até sete vezes mais rápidos do que as chamadas REST).
  • Só precisa de uma definição de serviço simples e não quer escrever uma biblioteca de cliente completa.

Para integrar o seu serviço com o gRPC:

  • Defina as mensagens de pedido e as respostas num ficheiro proto e compile-as.
  • Crie um servidor gRPC para processar pedidos e devolver respostas: deve ouvir a variável de ambiente PORT.
  • Crie um cliente que envie pedidos e processe respostas do servidor gRPC.
  • Opcionalmente, adicione autenticação.
  • Crie e implemente o seu serviço.

Definir e compilar mensagens num ficheiro proto

Não existem elementos adicionais ou específicos do Knative Serving para adicionar às suas definições de proto. Tal como acontece com qualquer outra utilização do gRPC, usa buffers de protocolo gRPC para definições de serviços e serialização de dados.

Criar um cliente gRPC

Não existem elementos adicionais ou específicos do Knative Serving a adicionar a um cliente que use o gRPC: siga as instruções do gRPC sobre a utilização de definições de serviços no código do cliente e os clientes de exemplo fornecidos nos tutoriais do gRPC específicos do idioma.

Ouvir pedidos gRPC num serviço Knative Serving

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

Ir

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

Abrir uma ligação gRPC a um serviço

Para abrir uma ligação gRPC a um serviço para que possa enviar mensagens gRPC, tem de especificar o domínio do anfitrião, que é o URL do serviço Knative Serving ou o domínio personalizado mapeado para esse serviço, juntamente com a porta 443, que é a porta esperada para ser usada pelo gRPC.

Ir


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

Enviar pedidos gRPC sem autenticação

O exemplo seguinte mostra como enviar um pedido sem autenticação, usando uma ligação gRPC configurada como mencionado anteriormente.

Ir


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