Tester des applications localement avec l'émulateur

Pour développer et tester votre application localement, vous pouvez utiliser l'émulateur Pub/Sub, qui fournit une émulation locale du service de production Pub/Sub. Vous exécutez l'instance Pub/Sub à l'aide de la Google Cloud CLI.

Pour exécuter votre application sur l'émulateur, commencez par lancer la et définissez les variables d'environnement. Votre application doit communiquer avec l'émulateur au lieu du service Pub/Sub de production. Les ressources créées et les messages publiés dans l'émulateur sont conservés pendant toute la durée de vie de la session de l'émulateur.

Avant de commencer

Avant d'utiliser l'émulateur Pub/Sub, vous devez remplir les conditions préalables suivantes :

Installer l'émulateur

Installez l'émulateur depuis une invite de commande :

gcloud components install pubsub-emulator
gcloud components update

Installer l'émulateur en tant qu'image de conteneur

Pour installer et exécuter l'émulateur en tant que conteneur, téléchargez et installez l'image Docker gCloud.

Démarrer l'émulateur

Pour démarrer l'émulateur, exécutez la commande pubsub start à partir d'une invite de commande : Avant d'exécuter la commande, remplacez PUBSUB_PROJECT_ID par une chaîne correspondant à un ID de projet Google Cloud valide. Il n'est pas nécessaire que la chaîne représente un vrai projet Google Cloud, L'émulateur Pub/Sub s'exécute localement.

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

Pour obtenir la liste complète des options, consultez la page gcloud beta emulators pubsub start.

Une fois l'émulateur démarré, un message semblable à celui-ci s'affiche:

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

Ce message indique que le serveur Pub/Sub s'exécute au niveau du point de terminaison de l'émulateur sur votre ordinateur local, et non sur le point de terminaison de Google Cloud. Toutes les opérations sont effectuées localement, y compris les suivantes :

  • Créer un sujet ou un abonnement
  • Publication…
  • Abonnement

Définir des variables d'environnement

Après avoir démarré l'émulateur, vous devez définir les variables d'environnement afin que votre application se connecte à l'émulateur, et non à Pub/Sub. Définissez ces variables d'environnement sur la même machine que celle utilisée pour exécuter votre application.

Vous devez définir les variables d'environnement chaque fois que vous démarrez l'émulateur. Elles dépendent des numéros de port attribués de manière dynamique, qui sont susceptibles d'être modifiés lorsque vous redémarrez l'émulateur.

Définir les variables automatiquement

Si votre application et l'émulateur s'exécutent sur la même machine, vous pouvez définir les variables d'environnement automatiquement comme suit :

Linux/macOS

Exécutez env-init à l'aide de la substitution de commande :

$(gcloud beta emulators pubsub env-init)

Windows

Créez et exécutez un fichier batch à l'aide du résultat de la commande env-init :

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

Votre application se connecte alors à l'émulateur Pub/Sub.

Définir les variables manuellement

Si votre application et l'émulateur s'exécutent sur des machines différentes, définissez les variables d'environnement manuellement :

  1. Exécutez la commande env-init :

     gcloud beta emulators pubsub env-init

  2. Sur la machine qui exécute votre application, définissez la variable d'environnement PUBSUB_EMULATOR_HOST ainsi que sa valeur, comme indiqué par le résultat de la commande env-init. Cette configuration connecte votre application à l'émulateur. Vous pouvez éventuellement définir l'environnement PUBSUB_PROJECT_ID du projet que vous souhaitez utiliser pour l'émulateur.

    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

Votre application se connecte alors à l'émulateur Pub/Sub.

Remarque : Si vous utilisez le serveur de développement local Python App Engine Standard, vous devez transmettre cette variable d'environnement via la ligne de commande comme suit :

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

dev_appserver.py est inclus dans votre [PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py.

Utiliser l'émulateur

Pour utiliser l'émulateur, vous devez disposer d'une application créée à l'aide des bibliothèques clientes Cloud. L'émulateur n'est pas compatible avec les commandes de la console Google Cloud ou de gcloud pubsub.

L'exemple suivant montre comment utiliser l'émulateur et une application qui utilise la bibliothèque cliente Cloud pour Python pour effectuer diverses opérations. Voici quelques exemples de ces opérations : créer un sujet, publier des messages et lire des messages.

Suivez les étapes ci-dessous sur la machine sur laquelle vous avez défini les variables d'environnement de l'émulateur :

  1. Récupérez les fichiers d'exemple Python pour Pub/Sub depuis GitHub en clonant l'intégralité du dépôt Python.

  2. Dans votre dépôt cloné, accédez au répertoire samples/snippets. Vous allez effectuer les étapes restantes dans ce répertoire.

  3. À partir du répertoire samples/snippets, installez les dépendances dont vous avez besoin pour exécuter l'exemple:

    pip install -r requirements.txt
    
  4. Créez un sujet :

     python publisher.py PUBSUB_PROJECT_ID create TOPIC_ID
    
  5. (Facultatif) Si vous ne disposez pas d'un point de terminaison push local pour tester les abonnements push dans l'émulateur, procédez comme suit : pour en créer un sur http://[::1]:3000/messages.

    1. Installez le serveur JSON.
      npm install -g json-server
      
    2. Démarrez le serveur JSON.
      json-server --port 3000 --watch db.json
      
      db.json contient le code de démarrage suivant:
      {
         "messages": []
      }
      
    3. Notez http://[::1]:3000/messages pour PUSH_ENDPOINT lors de l'étape suivante.
  6. Créez un abonnement associé au sujet :

    • Créez un abonnement pull :

      python subscriber.py PUBSUB_PROJECT_ID create TOPIC_ID SUBSCRIPTION_ID
      
    • Créez un abonnement push :

      python subscriber.py PUBSUB_PROJECT_ID create-push TOPIC_ID SUBSCRIPTION_ID \
      PUSH_ENDPOINT
      
  7. Publiez des messages sur le sujet :

     python publisher.py PUBSUB_PROJECT_ID publish TOPIC_ID
    
  8. Consultez les messages publiés sur le sujet :

    • Récupérez les messages de votre abonnement pull :

      python subscriber.py PUBSUB_PROJECT_ID receive SUBSCRIPTION_ID
      
    • Observez les messages envoyés à votre point de terminaison push local. Par exemple, les messages se présentent sous la forme suivante :

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

Accéder aux variables d'environnement

Dans tous les langages, à l'exception de Java et C#, les bibliothèques clientes Pub/Sub appellent automatiquement l'API s'exécutant dans l'instance locale plutôt que Pub/Sub, si vous avez défini PUBSUB_EMULATOR_HOST tel que décrit dans la section Définir des variables d'environnement.

Toutefois, afin d'utiliser l'émulateur, vous devez modifier votre code pour les bibliothèques clientes pour C# et Java :

C#

Avant d'essayer cet exemple, suivez les instructions de configuration pour C# du guide de démarrage rapide de Pub/Sub : utiliser les bibliothèques clientes. Pour en savoir plus, consultez les API C# Pub/Sub documentation de référence.

Pour vous authentifier auprès de Pub/Sub, configurez les identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.


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

Avant d'essayer cet exemple, suivez les instructions de configuration de Java dans le Guide de démarrage rapide de Pub/Sub bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API Pub/Sub Java.

Pour vous authentifier auprès de Pub/Sub, configurez les identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.


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;
import java.io.IOException;

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

Arrêter l'émulateur

Pour arrêter l'émulateur, appuyez sur les touches Ctrl+C.

Une fois l'émulateur arrêté, exécutez la commande suivante pour supprimer la variable d'environnement PUBSUB_EMULATOR_HOST, afin que votre application se connecte à Pub/Sub :

Linux/macOS
unset PUBSUB_EMULATOR_HOST
Fenêtres
set PUBSUB_EMULATOR_HOST=

Arguments de ligne de commande de l'émulateur

Pour en savoir plus sur les arguments de ligne de commande de l'émulateur Pub/Sub, consultez la page gcloud beta emulators pubsub.

Fonctionnalités compatibles

L'émulateur est compatible avec les fonctionnalités Pub/Sub suivantes :

  • Publier des messages
  • Recevoir des messages provenant d'abonnements push et pull
  • Trier des messages
  • Rouvrir des messages
  • Transférer des messages vers des files d'attente de lettres mortes
  • Stratégies de nouvelle tentative pour la distribution des messages
  • Compatibilité des schémas pour Avro

Limitations connues

  • Les RPC UpdateTopic et UpdateSnapshot ne sont pas compatibles.
  • Les opérations IAM ne sont pas compatibles.
  • La conservation configurable des messages n'est pas compatible. Tous les messages sont conservés indéfiniment.
  • Il n'est pas possible de définir une date d'expiration pour l'abonnement. Les abonnements n'expirent pas.
  • Le filtrage n'est pas compatible.
  • Schéma compatible pour les tampons de protocole.
  • Vous pouvez créer des abonnements BigQuery, mais ils n'envoient pas de messages à BigQuery.
  • Il n'est pas possible de rechercher un code temporel pour les abonnements commandés.

Pour signaler des problèmes, utilisez un outil public de suivi des problèmes.

Étape suivante

  • Pour savoir comment utiliser l'émulateur Pub/Sub avec minikube, consultez cet article de blog.