Test delle applicazioni in locale con l'emulatore

Per sviluppare e testare la tua applicazione localmente, puoi utilizzare l'emulatore Pub/Sub, che fornisce l'emulazione locale del servizio Pub/Sub di produzione. Esegui l'emulatore Pub/Sub utilizzando Google Cloud CLI.

Per eseguire l'applicazione rispetto all'emulatore, avvia prima l'emulatore e imposta le variabili di ambiente. La tua applicazione deve comunicare con l'emulatore anziché con il servizio Pub/Sub di produzione. Le risorse create e i messaggi pubblicati nell'emulatore vengono mantenuti per la durata della sessione dell'emulatore.

Prima di iniziare

Completa i seguenti prerequisiti prima di utilizzare l'emulatore Pub/Sub:

Installare l'emulatore

Installa l'emulatore da un prompt dei comandi:

gcloud components install pubsub-emulator
gcloud components update

Installare l'emulatore come immagine container

Per installare ed eseguire l'emulatore come container, scarica e installa l'immagine Docker gcloud.

Avvio dell'emulatore

Avvia l'emulatore richiamando pubsub start da un prompt dei comandi. Prima di eseguire il comando, sostituisci PUBSUB_PROJECT_ID con una stringaTrusted Cloud ID progetto valida. La stringa non deve rappresentare un progetto Trusted Cloud reale perché l'emulatore Pub/Sub viene eseguito localmente.

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

Consulta gcloud beta emulators pubsub start per un elenco completo dei flag.

Dopo aver avviato l'emulatore, viene visualizzato un messaggio simile al seguente:

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

Questo messaggio indica che il server Pub/Sub viene eseguito nell'endpoint dell'emulatore sulla tua macchina locale anziché nell'endpoint Trusted Cloud by S3NS . Tutte le operazioni vengono eseguite localmente, tra cui:

  • Creazione di un argomento o di una sottoscrizione
  • In fase di pubblicazione
  • Sottoscrizione in corso

Imposta le variabili di ambiente

Dopo aver avviato l'emulatore, devi impostare le variabili di ambiente in modo che l'applicazione si connetta all'emulatore anziché a Pub/Sub. Imposta queste variabili di ambiente sulla stessa macchina che utilizzi per eseguire l'applicazione.

Devi impostare le variabili di ambiente ogni volta che avvii l'emulatore. Le variabili di ambiente dipendono dai numeri di porta assegnati dinamicamente che potrebbero cambiare quando riavvii l'emulatore.

Impostazione automatica delle variabili

Se l'applicazione e l'emulatore vengono eseguiti sulla stessa macchina, puoi impostare automaticamente le variabili di ambiente:

Linux / macOS

Esegui env-init utilizzando la sostituzione dei comandi:

$(gcloud beta emulators pubsub env-init)

Windows

Crea ed esegui un file batch utilizzando l'output di env-init:

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

L'applicazione si connetterà ora all'emulatore Pub/Sub.

Impostazione manuale delle variabili

Se l'applicazione e l'emulatore vengono eseguiti su macchine diverse, imposta le variabili di ambiente manualmente:

  1. Esegui il comando env-init:

     gcloud beta emulators pubsub env-init

  2. Sulla macchina che esegue l'applicazione, imposta la variabile di ambiente PUBSUB_EMULATOR_HOST e il relativo valore come indicato dall'output del comando env-init. Questa configurazione connette l'applicazione all'emulatore. Puoi impostare facoltativamente la variabile di ambiente PUBSUB_PROJECT_ID per il progetto che vuoi utilizzare per l'emulatore.

    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

L'applicazione si connetterà ora all'emulatore Pub/Sub.

Nota:se utilizzi il server di sviluppo locale di App Engine Standard per Python, devi passare questa variabile di ambiente nella riga di comando nel seguente modo:

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

dev_appserver.py è incluso nel tuo [PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py.

Utilizzo dell'emulatore

Per utilizzare l'emulatore, devi disporre di un'applicazione creata utilizzando le librerie client di Cloud. L'emulatore non supporta i comandi Trusted Cloud della console o gcloud pubsub.

L'esempio seguente mostra l'utilizzo dell'emulatore e di un'applicazione che utilizza la libreria client Python Cloud per eseguire varie operazioni. Esempi di queste operazioni includono come creare un argomento, pubblicare messaggi e leggere messaggi.

Completa i seguenti passaggi sul computer in cui hai impostato le variabili di ambiente dell'emulatore:

  1. Recupera gli esempi Python di Pub/Sub da GitHub clonando l'intero repository Python.

  2. Nel repository clonato, vai alla directory samples/snippets. Completa il resto di questi passaggi in questa directory.

  3. Dalla directory samples/snippets, installa le dipendenze necessarie per eseguire l'esempio:

    pip install -r requirements.txt
    
  4. Per creare un argomento:

     python publisher.py PUBSUB_PROJECT_ID create TOPIC_ID
    
  5. (Facoltativo) Se non hai un endpoint push locale per testare le iscrizioni push nell'emulatore, completa i seguenti passaggi per crearne uno suhttp://[::1]:3000/messages.

    1. Installa JSON Server.
      npm install -g json-server
      
    2. Avvia il server JSON.
      json-server --port 3000 --watch db.json
      
      dove db.json contiene il seguente codice iniziale:
      {
         "messages": []
      }
      
    3. Prendi nota di http://[::1]:3000/messages per PUSH_ENDPOINT nel passaggio successivo.
  6. Crea una sottoscrizione per l'argomento:

    • Per creare una sottoscrizione pull:

      python subscriber.py PUBSUB_PROJECT_ID create TOPIC_ID SUBSCRIPTION_ID
      
    • Creare una sottoscrizione push:

      python subscriber.py PUBSUB_PROJECT_ID create-push TOPIC_ID SUBSCRIPTION_ID \
      PUSH_ENDPOINT
      
  7. Pubblica messaggi nell'argomento:

     python publisher.py PUBSUB_PROJECT_ID publish TOPIC_ID
    
  8. Leggi i messaggi pubblicati nell'argomento:

    • Recupera i messaggi dalla sottoscrizione pull:

      python subscriber.py PUBSUB_PROJECT_ID receive SUBSCRIPTION_ID
      
    • Osserva i messaggi inviati all'endpoint push locale. Ad esempio, i messaggi hanno il seguente aspetto:

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

Accedere alle variabili di ambiente

In tutti i linguaggi, ad eccezione di Java e C#, se hai impostato PUBSUB_EMULATOR_HOST come descritto in Impostazione delle variabili di ambiente, le librerie client Pub/Sub chiamano automaticamente l'API in esecuzione nell'istanza locale anziché Pub/Sub.

Tuttavia, le librerie client C# e Java richiedono di modificare il codice per utilizzare l'emulatore:

C#

Prima di provare questo esempio, segui le istruzioni di configurazione di C# nella guida rapida di Pub/Sub per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub C#.

Per eseguire l'autenticazione in Pub/Sub, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

Prima di eseguire gli esempi di codice, imposta la variabile di ambiente GOOGLE_CLOUD_UNIVERSE_DOMAIN su s3nsapis.fr.


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

Prima di provare questo esempio, segui le istruzioni di configurazione di Java nella guida rapida di Pub/Sub per l'utilizzo delle librerie client. Per saperne di più, consulta la documentazione di riferimento dell'API Pub/Sub Java.

Per eseguire l'autenticazione in Pub/Sub, configura le Credenziali predefinite dell'applicazione. Per ulteriori informazioni, consulta Configura l'autenticazione per un ambiente di sviluppo locale.

Prima di eseguire gli esempi di codice, imposta la variabile di ambiente GOOGLE_CLOUD_UNIVERSE_DOMAIN su s3nsapis.fr.


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

Arresto dell'emulatore

Per arrestare l'emulatore, premi Ctrl+C.

Dopo aver arrestato l'emulatore, esegui questo comando per rimuovere la variabile di ambiente PUBSUB_EMULATOR_HOST in modo che la tua applicazione si connetta a Pub/Sub:

Linux / macOS
unset PUBSUB_EMULATOR_HOST
Windows
set PUBSUB_EMULATOR_HOST=

Argomenti della riga di comando dell'emulatore

Per informazioni dettagliate sugli argomenti della riga di comando per l'emulatore Pub/Sub, vedi gcloud beta emulators pubsub.

Funzionalità supportate

L'emulatore supporta le seguenti funzionalità di Pub/Sub:

  • Pubblicazione di messaggi
  • Ricezione di messaggi da sottoscrizioni push e pull
  • Ordinamento dei messaggi
  • Ripetizione della visione dei messaggi
  • Inoltro di messaggi ad argomenti messaggi non recapitabili
  • Policy di ripetizione sulla consegna dei messaggi
  • Supporto dello schema per Avro

Limitazioni note

  • Le RPC UpdateTopic e UpdateSnapshot non sono supportate.
  • Le operazioni IAM non sono supportate.
  • La conservazione configurabile dei messaggi non è supportata; tutti i messaggi vengono conservati indefinitamente.
  • La scadenza dell'abbonamento non è supportata. Gli abbonamenti non scadono.
  • Il filtro non è supportato.
  • Supporto dello schema per i buffer di protocollo.
  • Le sottoscrizioni BigQuery possono essere create, ma non inviano messaggi a BigQuery.
  • La ricerca fino a un timestamp per le sottoscrizioni ordinate non è supportata.
  • Gli argomenti e le sottoscrizioni possono essere creati con Single Message Transforms (SMT), ma i messaggi non verranno trasformati.

Per segnalare problemi, invia una richiesta tramite il Public Issue Tracker.

Passaggi successivi

  • Per scoprire come utilizzare l'emulatore Pub/Sub con minikube, consulta questo post del blog.