Activa desde envío de Pub/Sub

Puedes usar Pub/Sub para enviar mensajes al extremo del servicio de Cloud Run, en el que, luego, se entregan los mensajes a los contenedores como solicitudes HTTP. No puedes usar suscripciones de extracción de Pub/Sub porque Cloud Run solo asigna CPU durante el procesamiento de una solicitud.

Debes procesar el mensaje y, luego, mostrar una respuesta cuando termines.

Si aprovechas las cuentas de servicio y los permisos de IAM, puedes usar Pub/Sub de manera segura y privada con Cloud Run sin tener que exponer el servicio de Cloud Run de forma pública. Solo la suscripción de Pub/Sub que configuraste puede invocar el servicio.

Entre los casos prácticos se incluyen los siguientes:

En esta página, se muestra cómo habilitar el servicio para procesar de manera segura los mensajes enviados desde una suscripción de Pub/Sub en el mismo proyecto de Google Cloud.

Para integrar el servicio a Pub/Sub, realiza las siguientes acciones:

  • Crea un tema de Pub/Sub.
  • Agrega código en el servicio de Cloud Run para responder a los mensajes de Pub/Sub que se enviaron al tema que creaste.
  • Crea una cuenta de servicio con los permisos necesarios.
  • Crea una suscripción de Pub/Sub y asóciala con la cuenta de servicio. Esta suscripción enviará al servicio cualquier mensaje que se publique en el tema.

Antes de comenzar

Si aún no lo haces, configura tu entorno como se describe en la página de configuración de Cloud Run. Deberás usar la línea de comandos de gcloud y un proyecto de Google Cloud para implementar el servicio de Cloud Run.

Agrega código para administrar mensajes de Pub/Sub

El servicio debe extraer el mensaje de la solicitud y mostrar un código de éxito esperado. En los siguientes fragmentos para los lenguajes seleccionados (puedes usar cualquier lenguaje), se muestra cómo hacerlo para un mensaje simple de Hello World:

Node.js

app.post('/', (req, res) => {
  if (!req.body) {
    const msg = 'no Pub/Sub message received';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }
  if (!req.body.message) {
    const msg = 'invalid Pub/Sub message format';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }

  const pubSubMessage = req.body.message;
  const name = pubSubMessage.data
    ? Buffer.from(pubSubMessage.data, 'base64').toString().trim()
    : 'World';

  console.log(`Hello ${name}!`);
  res.status(204).send();
});

Python

@app.route("/", methods=["POST"])
def index():
    envelope = request.get_json()
    if not envelope:
        msg = "no Pub/Sub message received"
        print(f"error: {msg}")
        return f"Bad Request: {msg}", 400

    if not isinstance(envelope, dict) or "message" not in envelope:
        msg = "invalid Pub/Sub message format"
        print(f"error: {msg}")
        return f"Bad Request: {msg}", 400

    pubsub_message = envelope["message"]

    name = "World"
    if isinstance(pubsub_message, dict) and "data" in pubsub_message:
        name = base64.b64decode(pubsub_message["data"]).decode("utf-8").strip()

    print(f"Hello {name}!")

    return ("", 204)

Go


// PubSubMessage is the payload of a Pub/Sub event.
// See the documentation for more details:
// https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
type PubSubMessage struct {
	Message struct {
		Data []byte `json:"data,omitempty"`
		ID   string `json:"id"`
	} `json:"message"`
	Subscription string `json:"subscription"`
}

// HelloPubSub receives and processes a Pub/Sub push message.
func HelloPubSub(w http.ResponseWriter, r *http.Request) {
	var m PubSubMessage
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Printf("ioutil.ReadAll: %v", err)
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}
	if err := json.Unmarshal(body, &m); err != nil {
		log.Printf("json.Unmarshal: %v", err)
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	name := string(m.Message.Data)
	if name == "" {
		name = "World"
	}
	log.Printf("Hello %s!", name)
}

Java

import java.util.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

// PubsubController consumes a Pub/Sub message.
@RestController
public class PubSubController {
  @RequestMapping(value = "/", method = RequestMethod.POST)
  public ResponseEntity receiveMessage(@RequestBody Body body) {
    // Get PubSub message from request body.
    Body.Message message = body.getMessage();
    if (message == null) {
      String msg = "Bad Request: invalid Pub/Sub message format";
      System.out.println(msg);
      return new ResponseEntity(msg, HttpStatus.BAD_REQUEST);
    }

    String data = message.getData();
    String target =
        !StringUtils.isEmpty(data) ? new String(Base64.getDecoder().decode(data)) : "World";
    String msg = "Hello " + target + "!";

    System.out.println(msg);
    return new ResponseEntity(msg, HttpStatus.OK);
  }
}

Debes codificar el servicio para mostrar un código de respuesta HTTP preciso. Los códigos de éxito, como HTTP 200204, confirman la recepción del procesamiento completo del mensaje de Pub/Sub. Los códigos de error, como HTTP 400500, indican que se volverá a intentar con el mensaje, como se describe en Recibe mensajes mediante suscripciones de envío.

Crea una cuenta de servicio para la suscripción

Debes crear una cuenta de servicio para asociarla con la suscripción de Pub/Sub y darle permiso a fin de invocar el servicio de Cloud Run. Los mensajes de Pub/Sub enviados al servicio de Cloud Run llevarán la identidad de esta cuenta de servicio.

Puedes usar una cuenta de servicio existente para representar la identidad de la suscripción de Pub/Sub o crear una nueva.

A fin de crear una cuenta de servicio nueva y darle permiso para invocar el servicio de Cloud Run, sigue estos pasos:

Console

  1. En Cloud Console, ve a la página Cuentas de servicio.

    Ir a Cuentas de servicio

  2. Selecciona un proyecto

  3. Ingresa un nombre de cuenta de servicio para mostrar en Cloud Console.

    Cloud Console genera un ID de cuenta de servicio a partir de este nombre. Si es necesario, edita el ID. No podrás cambiar el ID más adelante.

  4. Opcional: Ingresa una descripción de la cuenta de servicio.

  5. Haga clic en Crear.

  6. Haz clic en el campo Seleccionar una función.

  7. En Todas las funciones, selecciona Cloud Run > Invocador de Cloud Run.

  8. Haga clic en Listo.

Línea de comandos

  1. Crea la cuenta de servicio:

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
       --display-name "DISPLAYED_SERVICE_ACCOUNT_NAME"

    Reemplaza los siguientes elementos:

    • SERVICE_ACCOUNT_NAME por un nombre único en minúscula dentro del proyecto de Google Cloud, por ejemplo, my-invoker-service-account-name
    • DISPLAYED_SERVICE_ACCOUNT_NAME por el nombre que deseas mostrar para esta cuenta de servicio, por ejemplo, en la consola, My Invoker Service Account
  2. En Cloud Run, debes otorgar permiso a la cuenta de servicio para invocar el servicio:

    gcloud run services add-iam-policy-binding SERVICE \
       --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
       --role=roles/run.invoker

    Reemplaza los siguientes elementos:

    • SERVICE por el nombre del servicio que deseas que Pub/Sub invoque
    • SERVICE_ACCOUNT_NAME por el nombre de la cuenta de servicio
    • PROJECT_ID por el ID del proyecto de Google Cloud

Crea un tema de Pub/Sub

Las solicitudes al servicio se activan mediante mensajes publicados en un tema de Pub/Sub, por lo que deberás crear uno:

Console

  1. Visita la página Temas de Pub/Sub en Cloud Console.

    Página Temas de Pub/Sub

  2. Haz clic en Crear un tema.

  3. Ingresa un Nombre único para tu tema, por ejemplo, MyTopic.

Línea de comandos

gcloud pubsub topics create TOPIC-NAME

Reemplaza TOPIC-NAME con un nombre de tema único dentro del proyecto de Google Cloud.

Crea una suscripción de envío y asóciala con la cuenta de servicio

Después de crear el tema de Pub/Sub, debes suscribirte al servicio para recibir mensajes enviados a un tema y asociar la suscripción con la cuenta de servicio que creaste para el servicio. Puedes usar Cloud Console o la línea de comandos de gcloud:

Console

  1. Ve a la página Temas de Pub/Sub

    Página Temas de Pub/Sub

  2. Haz clic en el tema al que deseas suscribirte.

  3. Haz clic en Create a subscription (Crear una suscripción) para mostrar el formulario de suscripción:

    formulario de suscripción

    En el formulario, debes hacer lo siguiente:

    1. Especificar el tipo de entrega push (envío).
    2. Para la URL de extremos, especifica la URL del servicio, que se muestra en la página de detalles del servicio.
    3. En el menú desplegable Cuenta de servicio, selecciona la cuenta de servicio que creaste con los permisos necesarios.
    4. Establece el vencimiento de la suscripción y el plazo de confirmación de recepción como desees.
    5. Haz clic en Crear.
  4. Se completó la suscripción. Los mensajes publicados en el tema ahora se enviarán al servicio.

Línea de comandos

  1. Permite que Pub/Sub cree tokens de autenticación en el proyecto:

    gcloud projects add-iam-policy-binding PROJECT-ID \
         --member=serviceAccount:service-PROJECT-NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
         --role=roles/iam.serviceAccountTokenCreator

    Reemplaza los siguientes elementos:

    • PROJECT-ID por el ID del proyecto de Google Cloud
    • PROJECT-NUMBER por tu número de proyecto de Google Cloud

      El ID y el número del proyecto se enumeran en el panel Información del proyecto en Cloud Console para el proyecto.

  2. Crea una suscripción de Pub/Sub con la cuenta de servicio que creaste con los permisos necesarios:

    gcloud beta pubsub subscriptions create SUBSCRIPTION-ID --topic TOPIC-NAME \
       --push-endpoint=SERVICE-URL/ \
       --push-auth-service-account=SERVICE-ACCOUNT-NAME@PROJECT-ID.iam.gserviceaccount.com

    Reemplazar

    • TOPIC-NAME por el tema que creaste antes
    • SERVICE-URL por la URL HTTPS que se proporcionó cuando implementaste el servicio. Puedes encontrarla mediante el comando gcloud run services describe y la especificación del nombre del servicio; busca la línea del resultado que comienza con domain
    • PROJECT-ID por el ID del proyecto de Google Cloud

    La marca --push-auth-service-account activa las funciones de envío de Pub/Sub para la autenticación y la autorización.

  3. Se completó la suscripción. Los mensajes publicados en el tema ahora se enviarán al servicio. Puedes enviar un mensaje de prueba al tema mediante el siguiente comando:

    gcloud pubsub topics publish TOPIC --message "hello"

    Reemplaza TOPIC por el nombre del tema que creaste.

¿Qué sigue?