Utilizzo di gRPC

Questa pagina mostra i dettagli specifici di Cloud Run per gli sviluppatori che utilizzare gRPC per connettere un Cloud Run con altri servizi, ad esempio per fornire una comunicazione semplice e ad alte prestazioni di microservizi. Puoi utilizzare tutti i tipi di gRPC, i flussi di dati o uniario con Cloud Run.

I possibili casi d'uso includono:

  • Comunicazione tra microservizi interni.
  • Carichi di dati elevati (gRPC utilizza buffer di protocollo, fino a sette volte più veloci delle chiamate REST).
  • È necessaria solo una semplice definizione del servizio, non vuoi scrivere un libreria client.
  • Utilizza i gRPC in streaming nel tuo server gRPC per creare applicazioni e API più reattive.

Per integrare il tuo servizio con gRPC:

  • Configura il tuo servizio in modo che utilizzi HTTP/2 se usi gRPC streaming. HTTP/2 è il metodo di trasporto per lo streaming 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: dovrebbe ascoltare alla variabile di ambiente PORT.
  • Crea un client che invii le richieste e gestisca le risposte dal server gRPC.
  • Se vuoi, aggiungi l'autenticazione.
  • Crea ed esegui il deployment del tuo servizio.

Configurare il servizio per l'utilizzo di HTTP/2

Google consiglia di configurare il servizio in modo che utilizzi HTTP/2 se utilizzi gRPC con Cloud Run. Anche se alcune semplici funzionalità gRPC senza utilizzare HTTP/2, molte funzionalità gRPC, come flussi di dati e metadati, richiedono HTTP/2.

Definizione e compilazione di messaggi in un file proto

Non sono necessari elementi aggiuntivi o specifici di Cloud Run 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 ci sono ulteriori elementi o elementi specifici di Cloud Run da aggiungere a un client che utilizza gRPC: segui la documentazione di gRPC sull'utilizzo delle definizioni del servizio in codice cliente e i esempi di client forniti nella lingua Tutorial gRPC.

Scalabilità automatica e bilanciamento del carico

Cloud Run utilizza bilanciatori del carico gestiti da Google che mantengono separate le connessioni tra i client e le istanze Cloud Run. Con gRPC, la scalabilità automatica funziona come segue:

  • Le connessioni gRPC dei client terminano al bilanciatore del carico perimetrale. Modifica in corso... Le impostazioni di KeepAlive influiscono solo sulla connessione al bilanciatore del carico, non sulla di Cloud Run. Il client non riconosce quando un di eliminazione delle istanze.
  • Durante lo scale-in, il bilanciatore del carico chiude le connessioni inviando messaggi GOAWAY alle istanze di backend durante l'arresto.
  • Durante lo scale out, il bilanciatore del carico crea nuove connessioni al backend di Compute Engine. Tutte queste operazioni sono trasparenti per i clienti.
  • Durante la scalabilità automatica, molte istanze possono essere avviate e multiplexate in una singola connessione tra il client e il bilanciatore del carico proxy.
  • La concorrenza è determinata dal numero massimo di richieste in parallelo per istanza per i messaggi. In streaming, ogni stream viene conteggiato una volta rispetto al numero massimo di richieste simultanee.

Ascolto delle richieste gRPC in un servizio Cloud Run

L'unico requisito speciale per un server gRPC in esecuzione Cloud Run deve rimanere in ascolto sulla porta specificata dall'PORT come mostrato nel seguente 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 Cloud Run 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

L'esempio seguente 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)
}

Invio di richieste gRPC con autenticazione

L'esempio seguente mostra come utilizzare l'autenticazione tra i servizi, se che chiama il servizio abbia l'autorizzazione richiamatore per il servizio ricevente. Tieni presente che questo codice crea un'intestazione di autorizzazione con il token di identità corretto: questo è obbligatorio. Le autorizzazioni richieste e l'intestazione Autorizzazione sono descritti in dettaglio nelle autenticazione tra servizi.

Vai


import (
	"context"
	"fmt"
	"time"

	"google.golang.org/api/idtoken"
	"google.golang.org/grpc"
	grpcMetadata "google.golang.org/grpc/metadata"

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

// pingRequestWithAuth mints a new Identity Token for each request.
// This token has a 1 hour expiry and should be reused.
// audience must be the auto-assigned URL of a Cloud Run service or HTTP Cloud Function without port number.
func pingRequestWithAuth(conn *grpc.ClientConn, p *pb.Request, audience string) (*pb.Response, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// Create an identity token.
	// With a global TokenSource tokens would be reused and auto-refreshed at need.
	// A given TokenSource is specific to the audience.
	tokenSource, err := idtoken.NewTokenSource(ctx, audience)
	if err != nil {
		return nil, fmt.Errorf("idtoken.NewTokenSource: %w", err)
	}
	token, err := tokenSource.Token()
	if err != nil {
		return nil, fmt.Errorf("TokenSource.Token: %w", err)
	}

	// Add token to gRPC Request.
	ctx = grpcMetadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+token.AccessToken)

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

Codice di esempio per lo streaming gRPC

Per codice campione, fai riferimento all'implementazione di RouteGuide nel Tutorial sulle nozioni di base di gRPC per nella lingua che preferisci. Quando utilizzi Go, ad esempio, fai riferimento Implementazione di RouteGuide.