Usa gRPC

En esta página, se muestran detalles específicos de Cloud Run para desarrolladores que desean usar gRPC a fin de conectar un servicio de Cloud Run con otros servicios, por ejemplo, con el objetivo de proporcionar una comunicación simple y de alto rendimiento entre microservicios internos. Puedes usar todos los tipos de gRPC, de transmisión o unario, con Cloud Run.

Entre los casos prácticos se incluyen los siguientes:

  • Comunicación entre microservicios internos
  • Cargas altas de datos (gRPC usa búferes de protocolo, que son hasta siete veces más rápidos que las llamadas de REST).
  • Solo se necesita una definición de servicio simple; no es necesario que escribas una biblioteca cliente completa
  • Usa gRPC de transmisión en tu servidor de gRPC para compilar API y aplicaciones más responsivas.

Para integrar el servicio a gRPC, sigue estos pasos:

  • Configura tu servicio para que use HTTP/2 si usas gRPC de transmisión. HTTP/2 es el método de transporte para la transmisión de gRPC.
  • Define los mensajes y las respuestas de la solicitud en un archivo proto y compílalos.
  • Crea un servidor de gRPC para administrar las solicitudes y mostrar las respuestas: debe escuchar la variable de entorno PORT.
  • Crea un cliente que envíe solicitudes y administre respuestas desde el servidor de gRPC.
  • De manera opcional, agrega autenticación.
  • Compila y, luego, implementa el servicio.

Configura tu servicio para usar HTTP/2

Si usas gRPC de transmisión, configura tu servicio para usar HTTP/2.

Define y compila mensajes en un archivo proto

No hay elementos adicionales o específicos de Cloud Run para agregar a las definiciones de proto. Como con cualquier otro uso de gRPC, usa búferes de protocolo de gRPC para las definiciones de servicios y la serialización de datos.

Crea un cliente de gRPC

No hay elementos adicionales o específicos de Cloud Run para agregar a un cliente que usa gRPC. Sigue los documentos de gRPC acerca del uso de definiciones de servicios en el código del cliente y los clientes de muestra proporcionados en los instructivos de gRPC específicos del lenguaje.

Escucha las solicitudes de gRPC en un servicio de Cloud Run

El único requisito especial para un servidor de gRPC que se ejecuta en Cloud Run es escuchar en el puerto que la variable de entorno PORT especificó como se muestra en el código:

Comienza a usarlo

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

Abre una conexión de gRPC a un servicio

Para abrir una conexión de gRPC a un servicio a fin de que puedas enviar mensajes de gRPC, debes especificar el dominio del host, que es la URL del servicio de Cloud Run o el dominio personalizado que se asignó a ese servicio, junto con el puerto 443, que es el que se espera que use gRPC.

Comienza a usarlo


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

Envía solicitudes de gRPC sin autenticación

En el siguiente ejemplo, se muestra cómo enviar una solicitud sin autenticación mediante una conexión de gRPC que se configuró como se mencionó antes.

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

Envía solicitudes de gRPC con autenticación

En el siguiente ejemplo, se muestra cómo usar la autenticación entre servicios si el servicio que realiza la llamada tiene permiso para invocar el servicio receptor. Ten en cuenta que este código crea un encabezado de autorización que tiene el token de identidad adecuado; esto es obligatorio. El encabezado de autorización y los permisos obligatorios se describen en detalle en Autenticación de servicio a servicio.

Comienza a usarlo


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: %v", err)
	}
	token, err := tokenSource.Token()
	if err != nil {
		return nil, fmt.Errorf("TokenSource.Token: %v", 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)
}

Código de muestra para transmisión de gRPC

Para ver el código de muestra, consulta la implementación de RouteGuide en el instructivo de conceptos básicos de gRPC sobre el lenguaje que elijas. Por ejemplo, en el caso de Go, consulta Cómo implementar RouteGuide.