Aus Pub/Sub-Push auslösen

Sie können Pub/Sub verwenden, um Nachrichten an den Endpunkt Ihres Cloud Run-Dienstes zu übertragen, die anschließend als HTTP-Anfragen an Container gesendet werden. Sie können Pub/Sub-Pull-Abos nicht verwenden, da Cloud Run die CPU während der Verarbeitung einer Anfrage nur zuordnet.

Sie sollten die Nachricht verarbeiten und anschließend eine Antwort zurückgeben.

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.

Mögliche Anwendungsfälle:

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.

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.

Hinweis

Richten Sie Ihre Umgebung wie auf der Einrichtungsseite für Cloud Run beschrieben ein, falls Sie dies noch nicht getan haben. Sie müssen die gcloud-Befehlszeile und ein Google Cloud-Projekt verwenden, um Ihren Cloud Run-Dienst bereitzustellen.

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

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():
    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.
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);
  }
}

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.

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 Cloud Console die Seite Dienstkontoschlüssel erstellen auf.

    Seite "Dienstkonto erstellen"

  2. Wählen Sie aus der Dienstkontoliste die Option Neues Dienstkonto aus.

  3. Geben Sie im Feld Name des Dienstkontos den Namen ein, den Sie für das Dienstkonto verwenden möchten.

  4. Klicken Sie auf Erstellen.

  5. Kopieren Sie die E-Mail-Adresse des Dienstkontos, die Sie in den folgenden Schritten verwenden möchten.

  6. Klicken Sie auf Weiter, wenn Sie dazu aufgefordert werden, Berechtigungen anzugeben.

  7. Wechseln Sie in der Cloud Console zur Seite Cloud Run-Dienste.

    Zur Seite „Dienste“

  8. Wählen Sie Ihren Dienst in der angezeigten Liste aus.

  9. Klicken Sie gegebenenfalls ganz rechts auf der Seite auf die Ein-/Aus-Schaltfläche Infofeld anzeigen/Infofeld ausblenden, um Informationen anzuzeigen.

  10. Suchen Sie den Tab Berechtigungen und klicken Sie dort auf Mitglied hinzufügen.

  11. Fügen Sie die E-Mail-Adresse Ihres Dienstkontos in das Feld Neue Mitglieder ein.

  12. Wählen Sie im Drop-down-Menü "Rolle" Cloud Run > Cloud Run Invoker aus.

  13. Klicken Sie auf Speichern.

Befehlszeile

  1. Erstellen Sie das Dienstkonto:

    gcloud iam service-accounts create SERVICE-ACCOUNT_NAME \
       --display-name "DISPLAYED-SERVICE-ACCOUNT_NAME"

    Ersetzen Sie

    • 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.

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

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 entweder die 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 die Bestätigungsfrist wie gewünscht 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 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 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

    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.

  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