Apps lokal mit dem Emulator testen

Zum lokalen Entwickeln und Testen Ihrer Anwendung können Sie den Pub/Sub Emulator verwenden, der eine lokale Emulation des Pub/Sub-Produktionsdienstes bereitstellt. Sie führen den Pub/Sub-Emulator mit der Google Cloud CLI aus.

Um Ihre Anwendung mit dem Emulator auszuführen, starten Sie zuerst den Emulator und legen Sie die Umgebungsvariablen fest. Ihre Anwendung muss mit dem Emulator statt mit dem Produktions-Pub/Sub kommunizieren. Die erstellten Ressourcen und im Emulator veröffentlichte Nachrichten werden für die Dauer der Emulatorsitzung aufrechterhalten.

Hinweis

Erfüllen Sie die folgenden Voraussetzungen, bevor Sie den Pub/Sub-Emulator verwenden:

Emulator installieren

Installieren Sie den Emulator über eine Eingabeaufforderung:

gcloud components install pubsub-emulator
gcloud components update

Emulator als Container-Image installieren

Wenn Sie den Emulator als Container installieren und ausführen möchten, laden Sie das gcloud-Docker-Image herunter und installieren Sie es.

Emulator starten

Starten Sie den Emulator, indem Sie pubsub start über eine Eingabeaufforderung aufrufen. Ersetzen Sie vor dem Ausführen des Befehls PUBSUB_PROJECT_ID durch eine gültige Google Cloud Projekt-ID String. Der String muss kein echtes Google Cloud Projekt darstellen, da der Pub/Sub-Emulator lokal ausgeführt wird.

gcloud beta emulators pubsub start --project=PUBSUB_PROJECT_ID [options]

Eine vollständige Liste der Flags finden Sie unter gcloud beta emulators pubsub start.

Nachdem Sie den Emulator gestartet haben, wird eine Meldung angezeigt, die der folgenden ähnelt:

...
[pubsub] This is the Pub/Sub fake.
[pubsub] Implementation may be incomplete or differ from the real system.
...
[pubsub] INFO: Server started, listening on 8085

Diese Meldung gibt an, dass der Pub/Sub-Server auf dem Emulator-Endpunkt auf Ihrem lokalen Computer anstelle des Google Cloud Endpunkts ausgeführt wird. Alle Vorgänge werden lokal ausgeführt, einschließlich der folgenden:

  • Erstellen eines Themas oder Abos
  • Verlagswesen
  • Abonnieren

Umgebungsvariablen festlegen

Nachdem Sie den Emulator gestartet haben, müssen Sie die Umgebungsvariablen so festlegen, dass Ihre Anwendung eine Verbindung zum Emulator statt zu Pub/Sub herstellt. Legen Sie die Umgebungsvariablen auf dem Computer fest, auf dem auch die Anwendung ausgeführt wird.

Sie müssen die Umgebungsvariablen jedes Mal festlegen, wenn Sie den Emulator starten. Die Umgebungsvariablen hängen von dynamisch zugewiesenen Portnummern ab, die sich beim Neustart des Emulators ändern können.

Variablen automatisch einstellen

Wenn die Anwendung und der Emulator auf demselben Computer ausgeführt werden, können Sie die Umgebungsvariablen automatisch festlegen:

Linux/MacOS

Führen Sie env-init mit Befehlsersetzung aus:

$(gcloud beta emulators pubsub env-init)

Windows

Erstellen Sie eine Batchdatei und verwenden Sie bei der Ausführung die Ausgabe von env-init:

gcloud beta emulators pubsub env-init > set_vars.cmd && set_vars.cmd

Ihre Anwendung stellt jetzt eine Verbindung zum Pub/Sub-Emulator her.

Variablen manuell einstellen

Wenn die Anwendung und der Emulator auf unterschiedlichen Computern ausgeführt werden, legen Sie die Umgebungsvariablen manuell fest:

  1. Führen Sie den Befehl env-init aus:

     gcloud beta emulators pubsub env-init

  2. Legen Sie auf dem Computer, auf der Ihre Anwendung ausgeführt wird, die Umgebungsvariable PUBSUB_EMULATOR_HOST und den Wert entsprechend der Ausgabe des Befehls env-init fest. Mit dieser Konfiguration wird Ihre Anwendung mit dem Emulator verbunden. Optional können Sie die Umgebungsvariable PUBSUB_PROJECT_ID für das Projekt festlegen, das Sie für den Emulator verwenden möchten.

    Linux / MacOS
    export PUBSUB_EMULATOR_HOST=[::1]:8432
    export PUBSUB_PROJECT_ID=my-project-id
    Windows
    set PUBSUB_EMULATOR_HOST=[::1]:8432
    set PUBSUB_PROJECT_ID=my-project-id

Ihre Anwendung stellt jetzt eine Verbindung zum Pub/Sub-Emulator her.

Hinweis: Wenn Sie den lokalen Entwicklungsserver der Python App Engine Standard verwenden, müssen Sie diese Umgebungsvariable in der Befehlszeile wie folgt übergeben:

dev_appserver.py app.yaml --env_var PUBSUB_EMULATOR_HOST=${PUBSUB_EMULATOR_HOST}

dev_appserver.py ist in [PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py enthalten.

Emulator verwenden

Wenn Sie den Emulator verwenden möchten, erstellen Sie eine Anwendung mit den Cloud-Clientbibliotheken. Der Emulator unterstützt weder die Google Cloud Console noch gcloud pubsub Befehle.

Im folgenden Beispiel wird die Verwendung des Emulators und einer Anwendung veranschaulicht, die die Python Cloud-Clientbibliothek verwendet, um verschiedene Vorgänge auszuführen. Beispiele für diese Vorgänge sind das Erstellen eines Themas, das Veröffentlichen von Nachrichten und das Lesen von Nachrichten.

Führen Sie die folgenden Schritte auf dem Computer aus, auf dem Sie die Emulator Umgebungsvariablen festgelegt haben:

  1. Rufen Sie die Pub/Sub Python-Beispiele von GitHub ab. Klonen Sie dafür das vollständige Python-Repository.

  2. Wechseln Sie in Ihrem geklonten Repository zum Verzeichnis samples/snippets. Die restlichen Schritte werden in diesem Verzeichnis ausgeführt.

  3. Installieren Sie im Verzeichnis samples/snippets die Abhängigkeiten, die zum Ausführen des Beispiels erforderlich sind:

    pip install -r requirements.txt
    
  4. Erstellen Sie ein Thema:

     python publisher.py PUBSUB_PROJECT_ID create TOPIC_ID
    
  5. (Optional) Wenn Sie keinen lokalen Push-Endpunkt zum Testen von Push-Abos im Emulator haben, führen Sie die folgenden Schritte aus, um einen auf http://[::1]:3000/messages zu erstellen.

    1. Installieren Sie JSON-Server.
      npm install -g json-server
      
    2. Starten Sie JSON Server.
      json-server --port 3000 --watch db.json
      
      wobei db.json den folgenden Startcode enthält:
      {
         "messages": []
      }
      
    3. Notieren Sie sich im nächsten Schritt http://[::1]:3000/messages für PUSH_ENDPOINT.
  6. Erstellen Sie ein Abo für das Thema:

    • Erstellen Sie ein Pull-Abo:

      python subscriber.py PUBSUB_PROJECT_ID create TOPIC_ID SUBSCRIPTION_ID
      
    • Push-Abo erstellen:

      python subscriber.py PUBSUB_PROJECT_ID create-push TOPIC_ID SUBSCRIPTION_ID \
      PUSH_ENDPOINT
      
  7. Veröffentlichen Sie Nachrichten zum Thema:

     python publisher.py PUBSUB_PROJECT_ID publish TOPIC_ID
    
  8. Lesen Sie die zu dem Thema veröffentlichten Nachrichten:

    • Nachrichten aus Ihrem Pull-Abo abrufen:

      python subscriber.py PUBSUB_PROJECT_ID receive SUBSCRIPTION_ID
      
    • Beobachten Sie die an Ihren lokalen Push-Endpunkt zugestellten Nachrichten. Nachrichten sehen beispielsweise so aus:

      {
        "messages": [
            {
                "subscription": "projects/PUBSUB_PROJECT_ID/subscriptions/SUBSCRIPTION_ID",
                "message": {
                    "data": "TWVzc2FnZSBudW1iZXIgMQ==",
                    "messageId": "10",
                    "attributes": {}
                },
                "id": 1
            },
            ...
        ]
      }
      

Umgebungsvariablen aufrufen

In allen Sprachen außer Java und C# wird von den Pub/Sub-Clientbibliotheken anstelle von Pub/Sub automatisch die in der lokalen Instanz ausgeführte API aufgerufen, wenn Sie PUBSUB_EMULATOR_HOST wie unter Umgebungsvariablen festlegen beschrieben festgelegt haben.

Bei C#- und Java-Clientbibliotheken müssen Sie jedoch Ihren Code ändern, um den Emulator zu verwenden:

C#

Lesen Sie unter Pub/Sub-Kurzanleitung: Clientbibliotheken verwenden die Anleitung für die Einrichtung von C#, bevor Sie dieses Beispiel ausprobieren.C# Weitere Informationen finden Sie in der Pub/Sub C# API Referenzdokumentation.

Richten Sie zur Authentifizierung bei Pub/Sub die Standardanmeldedaten für Anwendungen (ADC) ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


using Google.Api.Gax;
using Google.Cloud.PubSub.V1;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

public class EmulatorSupportSample
{
    public async Task WithEmulatorAsync(string projectId, string topicId, string subscriptionId)
    {
        // Use EmulatorDetection.EmulatorOrProduction to create service clients that will
        // that will connect to the PubSub emulator if the PUBSUB_EMULATOR_HOST environment
        // variable is set, but will otherwise connect to the production environment.

        // Create the PublisherServiceApiClient using the PublisherServiceApiClientBuilder
        // and setting the EmulatorDection property.
        PublisherServiceApiClient publisherService = await new PublisherServiceApiClientBuilder
        {
            EmulatorDetection = EmulatorDetection.EmulatorOrProduction
        }.BuildAsync();

        // Use the client as you'd normally do, to create a topic in this example.
        TopicName topicName = new TopicName(projectId, topicId);
        publisherService.CreateTopic(topicName);

        // Create the SubscriberServiceApiClient using the SubscriberServiceApiClientBuilder
        // and setting the EmulatorDection property.
        SubscriberServiceApiClient subscriberService = await new SubscriberServiceApiClientBuilder
        {
            EmulatorDetection = EmulatorDetection.EmulatorOrProduction
        }.BuildAsync();

        // Use the client as you'd normally do, to create a subscription in this example.
        SubscriptionName subscriptionName = new SubscriptionName(projectId, subscriptionId);
        subscriberService.CreateSubscription(subscriptionName, topicName, pushConfig: null, ackDeadlineSeconds: 60);

        // Create the PublisherClient using PublisherClientBuilder to set the EmulatorDetection property.
        PublisherClient publisher = await new PublisherClientBuilder
        {
            TopicName = topicName,
            EmulatorDetection = EmulatorDetection.EmulatorOrProduction
        }.BuildAsync();
        // Use the client as you'd normally do, to send a message in this example.
        await publisher.PublishAsync("Hello, Pubsub");
        await publisher.ShutdownAsync(TimeSpan.FromSeconds(15));

        // Create the SubscriberClient using SubscriberClientBuild to set the EmulatorDetection property.
        SubscriberClient subscriber = await new SubscriberClientBuilder
        {
            SubscriptionName = subscriptionName,
            EmulatorDetection = EmulatorDetection.EmulatorOrProduction
        }.BuildAsync();
        List<PubsubMessage> receivedMessages = new List<PubsubMessage>();

        // Use the client as you'd normally do, to listen for messages in this example.
        await subscriber.StartAsync((msg, cancellationToken) =>
        {
            receivedMessages.Add(msg);
            Console.WriteLine($"Received message {msg.MessageId} published at {msg.PublishTime.ToDateTime()}");
            Console.WriteLine($"Text: '{msg.Data.ToStringUtf8()}'");
            // In this example we stop the subscriber when the message is received.
            // You may leave the subscriber running, and it will continue to received published messages
            // if any.
            // This is non-blocking, and the returned Task may be awaited.
            subscriber.StopAsync(TimeSpan.FromSeconds(15));
            // Return Reply.Ack to indicate this message has been handled.
            return Task.FromResult(SubscriberClient.Reply.Ack);
        });
    }
}

Java

Lesen Sie unter Pub/Sub-Kurzanleitung: Clientbibliotheken verwenden die Anleitung für die Einrichtung von Java, bevor Sie dieses Beispiel ausprobieren.Java Weitere Informationen finden Sie in der Pub/Sub Java API Referenzdokumentation.

Richten Sie zur Authentifizierung bei Pub/Sub die Standardanmeldedaten für Anwendungen (ADC) ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


import com.google.api.core.ApiFuture;
import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.api.gax.grpc.GrpcTransportChannel;
import com.google.api.gax.rpc.FixedTransportChannelProvider;
import com.google.api.gax.rpc.TransportChannelProvider;
import com.google.cloud.pubsub.v1.Publisher;
import com.google.cloud.pubsub.v1.TopicAdminClient;
import com.google.cloud.pubsub.v1.TopicAdminSettings;
import com.google.protobuf.ByteString;
import com.google.pubsub.v1.PubsubMessage;
import com.google.pubsub.v1.Topic;
import com.google.pubsub.v1.TopicName;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

public class UsePubSubEmulatorExample {
  public static void main(String... args) throws Exception {
    String hostport = System.getenv("PUBSUB_EMULATOR_HOST");
    ManagedChannel channel = ManagedChannelBuilder.forTarget(hostport).usePlaintext().build();
    try {
      TransportChannelProvider channelProvider =
          FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel));
      CredentialsProvider credentialsProvider = NoCredentialsProvider.create();

      // Set the channel and credentials provider when creating a `TopicAdminClient`.
      // Can be done similarly for a `SubscriptionAdminClient`.
      TopicAdminClient topicAdminClient =
          TopicAdminClient.create(
              TopicAdminSettings.newBuilder()
                  .setTransportChannelProvider(channelProvider)
                  .setCredentialsProvider(credentialsProvider)
                  .build());

      TopicName topicName = TopicName.of("my-project-id", "my-topic-id");
      Topic topic = topicAdminClient.createTopic(topicName);
      System.out.println("Created topic: " + topic.getName());

      // Set the channel and credentials provider when creating a `Publisher`.
      // Can be done similarly for a `Subscriber`.
      Publisher publisher =
          Publisher.newBuilder(topicName)
              .setChannelProvider(channelProvider)
              .setCredentialsProvider(credentialsProvider)
              .build();

      String message = "Hello World!";
      ByteString data = ByteString.copyFromUtf8(message);
      PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();

      ApiFuture<String> messageIdFuture = publisher.publish(pubsubMessage);
      String messageId = messageIdFuture.get();
      System.out.println("Published message ID: " + messageId);
    } finally {
      channel.shutdown();
    }
  }
}

Emulator beenden

Drücken Sie zum Beenden des Emulators Strg+C.

Nachdem Sie den Emulator beendet haben, führen Sie den folgenden Befehl aus, um die Umgebungsvariable PUBSUB_EMULATOR_HOST zu entfernen, damit Ihre Anwendung eine Verbindung zu Pub/Sub herstellt:

Linux / MacOS
unset PUBSUB_EMULATOR_HOST
Windows
set PUBSUB_EMULATOR_HOST=

Befehlszeilenargumente des Emulators

Weitere Informationen zu Befehlszeilenargumenten für den Pub/Sub-Emulator finden Sie unter gcloud beta emulators pubsub.

Unterstützte Features

Der Emulator unterstützt die folgenden Pub/Sub-Features:

  • Nachrichten veröffentlichen
  • Nachrichten von Push- und Pull-Abos empfangen
  • Nachrichten in eine Reihenfolge bringen
  • Nachrichten wiedergeben
  • Nachrichten an Themen für unzustellbare Nachrichten weiterleiten
  • Richtlinien für Wiederholungsversuche bei der Nachrichtenübermittlung
  • Schemaunterstützung für Avro
  • Filtern

Bekannte Einschränkungen

  • Die RPCs UpdateTopic und UpdateSnapshot werden nicht unterstützt.
  • IAM-Vorgänge werden nicht unterstützt.
  • Die konfigurierbare Nachrichtenaufbewahrung wird nicht unterstützt. Alle Nachrichten werden auf unbestimmte Zeit aufbewahrt.
  • Der Ablauf von Abos wird nicht unterstützt. Abos laufen nicht ab.
  • Schemaunterstützung für Protokollzwischenspeicher
  • BigQuery-Abos können erstellt werden, senden aber keine Nachrichten an BigQuery.
  • Das Suchen nach einem Zeitstempel für geordnete Abos wird nicht unterstützt.
  • Themen und Abos können mit Single Message Transforms (SMTs) erstellt werden, Nachrichten werden jedoch nicht transformiert.

Wenn Sie Probleme melden möchten, senden Sie eine Anfrage an die öffentliche Problemverfolgung.

Nächste Schritte

  • Informationen zur Verwendung des Pub/Sub-Emulators mit minikube finden Sie in diesem Blogpost.