Aus Pub/Sub-Push auslösen

Auf dieser Seite wird beschrieben, wie Sie Pub/Sub verwenden, um Nachrichten an den Endpunkt Ihres Cloud Run-Dienstes zu übertragen. Die Nachrichten werden dann als HTTP-Anfragen an Container geliefert. Auf dieser Seite wird beschrieben, wie Sie Ihrem Dienst ermöglichen, Nachrichten, die von einem Pub/Sub-Abo im selben Google Cloud-Projekt gesendet wurden, sicher zu verarbeiten.

Mithilfe von Dienstkonten und IAM-Berechtigungen können Sie Pub/Sub sicher und privat mit Cloud Run verwenden, ohne Ihren Cloud Run-Dienst öffentlich zugänglich machen zu müssen. Nur das von Ihnen eingerichtete Pub/Sub-Abo kann Ihren Dienst aufrufen.

Bestätigungsfristen für Cloud Run

Achten Sie darauf, dass Sie die Bestätigungsfrist für das Pub/Sub-Abo (ackDeadlineSeconds) auf den maximal zulässigen Wert (600 Sekunden) festlegen. Ihr Cloud Run-Dienst muss die Pub/Sub-Nachricht bestätigen, wozu er innerhalb von 600 Sekunden eine Antwort zurückzugeben hat. Andernfalls sendet Pub/Sub die Nachricht noch einmal, was bedeutet, dass Ihr Cloud Run-Dienst zweimal getriggert wird.

Anwendungsfälle

Mögliche Anwendungsfälle:

Überblick über die Integration

Zum Integrieren Ihres Dienstes in Pub/Sub:

  • Erstellen Sie ein Pub/Sub-Thema.
  • Fügen Sie Ihrem Cloud Run-Dienst Code hinzu, um auf die Pub/Sub-Nachrichten zu antworten, die an das von Ihnen erstellte Thema gesendet wurden.
  • Erstellen Sie ein Dienstkonto mit den erforderlichen Berechtigungen.
  • Erstellen Sie ein Pub/Sub-Abo und verknüpfen es mit dem Dienstkonto. Dieses Abo sendet alle Nachrichten, die zum Thema veröffentlicht wurden, an Ihren Dienst.

Vorbereitung

  • Richten Sie Ihre Umgebung wie auf der Einrichtungsseite für Cloud Run beschrieben ein, falls Sie dies noch nicht getan haben.
  • In dieser Anleitung wird davon ausgegangen, dass Sie bereits einen Cloud Run-Dienst haben und Code hinzufügen möchten, der ihn in Pub/Sub integriert. Wenn Sie keinen solchen Dienst haben, sollten Sie die Cloud Run-Anleitung für Pub/Sub verwenden, anstatt diese Seite zu verfolgen.

Code für die Verarbeitung der Nachrichten von Pub/Sub hinzufügen

Bearbeiten Sie Ihren vorhandenen Dienstcode, um Code hinzuzufügen, der für Pub/Sub erforderlich ist. Ihr Dienst muss die Nachricht aus der Anfrage extrahieren und einen erwarteten Erfolgscode zurückgeben. Die folgenden Snippets für ausgewählte Sprachen, für die Sie jede Sprache verwenden können, zeigen, wie dies für eine einfache Hello-World-Nachricht funktioniert:

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():
    """Receive and parse Pub/Sub messages."""
    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)

Einfach loslegen (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
	}
	// byte slice unmarshalling handles base64 decoding.
	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 com.example.cloudrun.Body;
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<String> 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);
  }
}

Sie müssen den Dienst so programmieren, dass ein genauer HTTP-Antwortcode zurückgegeben wird. Erfolgscodes wie HTTP 200 oder 204 bestätigen die vollständige Verarbeitung der Pub/Sub-Nachricht. Fehlercodes wie HTTP 400 oder 500 zeigen an, dass der Versand der Nachricht noch einmal versucht wird. Weitere Informationen finden Sie unter Nachrichten mit Push empfangen.

Erstellen Sie den Cloud Run-Dienst und stellen Sie ihn bereit, nachdem Sie ihn mit dem obigen Pub/Sub-Code aktualisiert haben.

Dienstkonto für das Abo erstellen

Sie müssen ein Dienstkonto erstellen, das mit Ihrem Pub/Sub-Abo verknüpft werden soll, und ihm die Berechtigung zum Aufrufen Ihres Cloud Run-Dienstes erteilen. Pub/Sub-Nachrichten, die an Ihren Cloud Run-Dienst gesendet werden, tragen die Identität dieses Dienstkontos.

Sie können ein vorhandenes Dienstkonto verwenden, um die Identität des Pub/Sub-Abos darzustellen. Sie können auch ein neues erstellen.

So erstellen Sie ein neues Dienstkonto und erteilen ihm die Berechtigung zum Aufrufen des Cloud Run-Dienstes:

Console

  1. Rufen Sie in der Google Cloud Console die Seite Dienstkonten auf:

    Zur Seite „Dienstkonten“

  2. Wählen Sie ein Projekt aus.

  3. Geben Sie einen Dienstkontonamen ein, der in der Google Cloud Console angezeigt werden soll.

    Die Google Cloud Console generiert anhand dieses Namens eine Dienstkonto-ID. Bearbeiten Sie gegebenenfalls die ID. Sie können die ID später nicht mehr ändern.

  4. Optional: Geben Sie eine Beschreibung für das Dienstkonto ein.

  5. Klicken Sie auf Erstellen und fortfahren.

  6. Optional: Klicken Sie auf das Feld Rolle auswählen.

  7. Wählen Sie Cloud Run > Cloud Run Invoker aus.

  8. Klicken Sie auf Fertig.

Befehlszeile

  1. Erstellen Sie das Dienstkonto:

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

    Ersetzen

    • SERVICE_ACCOUNT_NAME durch einen Namen in Kleinbuchstaben, der in Ihrem Google Cloud-Projekt eindeutig ist, z. B. my-invoker-service-account-name.
    • DISPLAYED_SERVICE_ACCOUNT_NAME durch den Namen, den Sie für dieses Dienstkonto anzeigen möchten, z. B. in der Konsole wie etwa My Invoker Service Account.
  2. Erteilen Sie Ihrem Dienstkonto für Cloud Run die Berechtigung, den Dienst aufzurufen:

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

    Ersetzen Sie

    • SERVICE durch den Namen des Dienstes, der von Pub/Sub aufgerufen werden soll.
    • SERVICE_ACCOUNT_NAME durch den Namen des Dienstkontos.
    • PROJECT_ID durch Ihre Google Cloud-Projekt-ID.
  3. Gewähren Sie Ihrem Dienstkonto Zugriff auf das Projekt, damit es berechtigt ist, bestimmte Aktionen für die Ressourcen in Ihrem Projekt auszuführen:

    gcloud projects add-iam-policy-binding RESOURCE_ID \
       --member=PRINCIPAL --role=roles/run.invoker

    Ersetzen

    • RESOURCE_ID: Ihre Google Cloud-Projekt-ID.

    • PRINCIPAL: Eine Kennung für das Hauptkonto bzw. Mitglied, die normalerweise die folgende Form hat: PRINCIPAL_TYPE:ID. Beispiel: user:my-user@example.com. Eine vollständige Liste der für PRINCIPAL zulässigen Werte finden Sie in der Referenz zur Richtlinienbindung.

Terraform

Informationen zum Anwenden oder Entfernen einer Terraform-Konfiguration finden Sie unter Grundlegende Terraform-Befehle.

  1. Fügen Sie Ihrer vorhandenen .tf-Datei Folgendes hinzu, um ein Dienstkonto zu erstellen:

    resource "google_service_account" "sa" {
      account_id   = "cloud-run-pubsub-invoker"
      display_name = "Cloud Run Pub/Sub Invoker"
    }
  2. Fügen Sie der vorhandenen Datei .tf Folgendes hinzu, um Ihrem Dienstkonto die Berechtigung zum Aufrufen Ihres Dienstes zu erteilen:

    resource "google_cloud_run_service_iam_binding" "binding" {
      location = google_cloud_run_v2_service.default.location
      service  = google_cloud_run_v2_service.default.name
      role     = "roles/run.invoker"
      members  = ["serviceAccount:${google_service_account.sa.email}"]
    }

Pub/Sub-Thema erstellen

Anfragen an Ihren Dienst werden durch Nachrichten ausgelöst, die in einem Pub/Sub-Thema veröffentlicht werden. Daher müssen Sie ein Thema erstellen:

Console

  1. Rufen Sie in der Google Cloud Console die Seite der Pub/Sub-Themen auf.

    Seite "Pub/Sub-Themen"

  2. Klicken Sie auf Thema erstellen.

  3. Geben Sie einen eindeutigen Namen für Ihr Thema ein, zum Beispiel "MeinThema".

Befehlszeile

gcloud pubsub topics create TOPIC-NAME

Ersetzen Sie TOPIC-NAME durch einen Themennamen, der in Ihrem Google Cloud-Projekt eindeutig ist.

Terraform

Informationen zum Anwenden oder Entfernen einer Terraform-Konfiguration finden Sie unter Grundlegende Terraform-Befehle.

In diesem Abschnitt wird gezeigt, wie Sie Terraform verwenden, um mithilfe der Ressource google_pubsub_topic vom Google Cloud Platform-Anbieter Ihren Dienst in einer Terraform-Konfiguration zu definieren.

Fügen Sie der Datei .tf den folgenden Inhalt hinzu:

resource "google_pubsub_topic" "default" {
  name = "pubsub_topic"
}

Push-Abo erstellen und mit dem Dienstkonto verknüpfen

Nachdem Sie das Pub/Sub-Thema erstellt haben, müssen Sie Ihren Dienst abonnieren, um Nachrichten zu erhalten, die an ein Thema gesendet werden. Außerdem müssen Sie das Abo mit dem Dienstkonto verknüpfen, das Sie für den Dienst erstellt haben. Sie können dazu die Google Cloud Console oder die gcloud-Befehlszeile verwenden:

Console

  1. Zur Seite "Pub/Sub-Themen"

    Seite "Pub/Sub-Themen"

  2. Klicken Sie auf das Thema, das Sie abonnieren möchten.

  3. Klicken Sie auf Abo erstellen, um das Anmeldeformular anzuzeigen:

    Anmeldeformular

    Im Formular:

    1. Geben Sie den Push-Zustellungstyp an.
    2. Geben Sie als Endpunkt-URL die URL Ihres Dienstes an, die auf der Seite mit den Dienstdetails angezeigt wird.
    3. Wählen Sie im Drop-down-Menü Dienstkonto das Dienstkonto aus, das Sie mit den erforderlichen Berechtigungen erstellt haben.
    4. Legen Sie den Ablauf des Abos und eine Bestätigungsfrist von 600 Sekunden fest.
    5. Klicken Sie auf Erstellen.
  4. Das Abo ist abgeschlossen. Nachrichten, die zum Thema gepostet wurden, werden nun an Ihren Dienst weitergeleitet.

Befehlszeile

  1. Erlauben Sie Pub/Sub, Authentifizierungstokens in Ihrem Projekt zu erstellen:

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

    Ersetzen Sie

    • PROJECT-ID durch Ihre Google Cloud-Projekt-ID.
    • PROJECT-NUMBER durch Ihre Google Cloud-Projektnummer.

      Die Projekt-ID und die Projektnummer werden im Bereich Projektinformationen in der Google Cloud Console für Ihr Projekt aufgeführt.

  2. Erstellen Sie ein Pub/Sub-Abo mit dem Dienstkonto, das Sie mit den erforderlichen Berechtigungen erstellt haben:

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

    Ersetzen

    • TOPIC-NAME durch das zuvor erstellte Thema.
    • SERVICE-URL durch die HTTPS-URL, die bei der Bereitstellung des Dienstes angegeben wurde. Sie finden sie mit dem Befehl gcloud run services describe. Geben Sie dabei den Namen Ihres Dienstes an. Suchen Sie nach der Rückgabezeile, die mit domain beginnt.
    • PROJECT-ID durch Ihre Google Cloud-Projekt-ID.

    Das Flag --push-auth-service-account aktiviert die Pub/Sub-Push-Funktion für die Authentifizierung und Autorisierung.

    Beachten Sie, dass die Bestätigungsfrist auf maximal 600 Sekunden festgelegt ist.

  3. Das Abo ist abgeschlossen. Nachrichten, die zum Thema gepostet wurden, werden nun an Ihren Dienst weitergeleitet. Mit dem folgenden Befehl können Sie eine Testnachricht an das Thema senden:

    gcloud pubsub topics publish TOPIC --message "hello"

    Ersetzen Sie TOPIC durch den Namen des von Ihnen erstellten Themas.

Terraform

Informationen zum Anwenden oder Entfernen einer Terraform-Konfiguration finden Sie unter Grundlegende Terraform-Befehle.

  1. Erlauben Sie Pub/Sub, Authentifizierungstokens in Ihrem Projekt zu erstellen. Fügen Sie der Datei .tf Folgendes hinzu:

    resource "google_project_service_identity" "pubsub_agent" {
      provider = google-beta
      project  = data.google_project.project.project_id
      service  = "pubsub.googleapis.com"
    }
    
    resource "google_project_iam_binding" "project_token_creator" {
      project = data.google_project.project.project_id
      role    = "roles/iam.serviceAccountTokenCreator"
      members = ["serviceAccount:${google_project_service_identity.pubsub_agent.email}"]
    }
  2. Erstellen Sie ein Pub/Sub-Abo mit dem Dienstkonto, das Sie mit den erforderlichen Berechtigungen erstellt haben. Fügen Sie der Datei .tf Folgendes hinzu:

    resource "google_pubsub_subscription" "subscription" {
      name  = "pubsub_subscription"
      topic = google_pubsub_topic.default.name
      push_config {
        push_endpoint = google_cloud_run_v2_service.default.uri
        oidc_token {
          service_account_email = google_service_account.sa.email
        }
        attributes = {
          x-goog-version = "v1"
        }
      }
      depends_on = [google_cloud_run_v2_service.default]
    }
  3. Das Abo ist abgeschlossen. Nachrichten, die zum Thema gepostet wurden, werden nun an Ihren Dienst weitergeleitet. Mit dem folgenden Befehl können Sie eine Testnachricht an das Thema senden:

    gcloud pubsub topics publish TOPIC --message "hello"

    Ersetzen Sie TOPIC durch den Namen des von Ihnen erstellten Themas.

Nächste Schritte