Richiamo con gRPC

Questa pagina mostra dettagli specifici per la pubblicazione di Knative per gli sviluppatori che vogliono utilizzare gRPC per collegare un servizio di pubblicazione Knative ad altri servizi, ad esempio per fornire una comunicazione semplice e ad alte prestazioni tra i microservizi interni. Knative serving supporta sia le chiamate gRPC unitarie sia quelle di streaming.

gRPC Unary

In una chiamata RPC unaria, il client invia una singola richiesta al server e riceve una singola risposta, in modo simile a una normale chiamata di funzione:
rpc SayHello(HelloRequest) returns (HelloResponse);

Streaming gRPC

Con gRPC sono disponibili le seguenti opzioni di streaming. RPC di streaming del server in cui il client invia una richiesta al server e riceve uno stream da leggere contenente una sequenza di messaggi. Il client legge lo stream restituito finché non ci sono più messaggi.

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);

RPC di streaming client in cui il client scrive una sequenza di messaggi e li invia al server in uno stream. Dopo che il client ha terminato di scrivere i messaggi, attende che il server restituisca la risposta.

rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);

RPC di streaming bidirezionale in cui il client e il server inviano messaggi in due stream di lettura/scrittura che operano in modo indipendente.

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

Ecco alcuni possibili casi d'uso:

  • Comunicazione tra microservizi interni.
  • Carichi elevati di dati (gRPC utilizza i buffer di protocollo, che sono fino a sette volte più veloci delle chiamate REST).
  • È necessaria solo una semplice definizione di servizio, non è necessario scrivere una biblioteca client completa.

Per integrare il tuo servizio con gRPC:

  • Definisci i messaggi di richiesta e le risposte in un file proto e compilali.
  • Crea un server gRPC per gestire le richieste e restituire le risposte: deve ascoltare la variabile di ambiente PORT.
  • Crea un client che invia richieste e gestisce le risposte del server gRPC.
  • Se vuoi, aggiungi l'autenticazione.
  • Crea ed esegui il deployment del tuo servizio.

Definire e compilare i messaggi in un file proto

Non sono presenti elementi aggiuntivi o specifici di Knative serving da aggiungere alle definizioni proto. Come per qualsiasi altro utilizzo di gRPC, utilizzi buffer del protocollo gRPC per le definizioni dei servizi e la serializzazione dei dati.

Creazione di un client gRPC

Non sono presenti elementi aggiuntivi o specifici di Knative da aggiungere a un client che utilizza gRPC: segui le indicazioni riportate nella documentazione di gRPC sull'utilizzo delle definizioni di servizio nel codice client e i client di esempio forniti nei tutorial gRPC specifici per ogni linguaggio.

Ascolto delle richieste gRPC in un servizio Knative serving

L'unico requisito speciale per un server gRPC in esecuzione in Knative serving è ascoltare sulla porta specificata dalla variabile di ambiente PORT come mostrato nel codice:

Vai

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

Apertura di una connessione gRPC a un servizio

Per aprire una connessione gRPC a un servizio in modo da poter inviare messaggi gRPC, devi specificare il dominio host, ovvero l'URL del servizio di pubblicazione Knative o il dominio personalizzato mappato a quel servizio, insieme alla porta 443, che è la porta che dovrebbe essere utilizzata da gRPC.

Vai


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

Invio di richieste gRPC senza autenticazione

Il seguente esempio mostra come inviare una richiesta senza autenticazione, utilizzando una connessione gRPC configurata come indicato in precedenza.

Vai


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