Menguji aplikasi secara lokal dengan emulator

Untuk mengembangkan dan menguji aplikasi secara lokal, Anda dapat menggunakan emulator Pub/Sub, yang menyediakan emulasi lokal layanan Pub/Sub produksi. Anda menjalankan emulator Pub/Sub menggunakan Google Cloud CLI.

Untuk menjalankan aplikasi Anda di emulator, mulai emulator terlebih dahulu dan tetapkan variabel lingkungan. Aplikasi Anda harus berkomunikasi dengan emulator, bukan layanan Pub/Sub produksi. Resource yang dibuat dan pesan yang dipublikasikan ke emulator dipertahankan selama sesi emulator.

Sebelum memulai

Selesaikan prasyarat berikut sebelum Anda menggunakan emulator Pub/Sub:

Menginstal emulator

Instal emulator dari command prompt:

gcloud components install pubsub-emulator
gcloud components update

Menginstal emulator sebagai image container

Untuk menginstal dan menjalankan emulator sebagai penampung, download dan instal image Docker gCloud.

Memulai emulator

Mulai emulator dengan memanggil pubsub start dari command prompt. Sebelum menjalankan perintah, ganti PUBSUB_PROJECT_ID dengan string project ID Google Cloud yang valid. String tidak perlu mewakili project Google Cloud yang sebenarnya karena emulator Pub/Sub berjalan secara lokal.

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

Lihat gcloud beta emulators pubsub start untuk mengetahui daftar lengkap flag.

Setelah memulai emulator, Anda akan melihat pesan yang menyerupai berikut:

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

Pesan ini menunjukkan bahwa server Pub/Sub berjalan di endpoint emulator di komputer lokal Anda, bukan endpoint Google Cloud. Semua operasi terjadi secara lokal, termasuk hal berikut:

  • Membuat topik atau langganan
  • Penerbitan
  • Berlangganan

Menyetel variabel lingkungan

Setelah memulai emulator, Anda harus menetapkan variabel lingkungan agar aplikasi Anda terhubung ke emulator, bukan Pub/Sub. Tetapkan variabel lingkungan ini di mesin yang sama dengan yang Anda gunakan untuk menjalankan aplikasi.

Anda harus menetapkan variabel lingkungan setiap kali memulai emulator. Variabel lingkungan bergantung pada nomor port yang ditetapkan secara dinamis yang dapat berubah saat Anda memulai ulang emulator.

Menetapkan variabel secara otomatis

Jika aplikasi dan emulator berjalan di komputer yang sama, Anda dapat menetapkan variabel lingkungan secara otomatis:

Linux / macOS

Jalankan env-init menggunakan penggantian perintah:

$(gcloud beta emulators pubsub env-init)

Windows

Buat dan jalankan file batch menggunakan output dari env-init:

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

Aplikasi Anda sekarang akan terhubung ke emulator Pub/Sub.

Menetapkan variabel secara manual

Jika aplikasi dan emulator Anda berjalan di mesin yang berbeda, tetapkan variabel lingkungan secara manual:

  1. Jalankan perintah env-init:

     gcloud beta emulators pubsub env-init

  2. Di mesin yang menjalankan aplikasi Anda, tetapkan variabel dan nilai lingkungan PUBSUB_EMULATOR_HOST seperti yang diarahkan oleh output perintah env-init. Konfigurasi ini menghubungkan aplikasi Anda ke emulator. Secara opsional, Anda dapat menetapkan variabel lingkungan PUBSUB_PROJECT_ID untuk project yang ingin digunakan untuk emulator.

    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

Aplikasi Anda sekarang akan terhubung ke emulator Pub/Sub.

Catatan: Jika menggunakan server pengembangan lokal Python App Engine Standard, Anda harus meneruskan variabel lingkungan ini di command line sebagai berikut:

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

dev_appserver.py disertakan dalam [PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py Anda.

Menggunakan emulator

Untuk menggunakan emulator, Anda harus memiliki aplikasi yang di-build menggunakan Library Klien Cloud. Emulator tidak mendukung konsol Google Cloud atau perintah gcloud pubsub.

Contoh berikut menunjukkan penggunaan emulator dan aplikasi yang menggunakan Library Klien Cloud Python untuk melakukan berbagai operasi. Contoh operasi ini mencakup cara membuat topik, memublikasikan pesan, dan membaca pesan.

Selesaikan langkah-langkah berikut di komputer tempat Anda menetapkan variabel lingkungan emulator:

  1. Dapatkan contoh Python Pub/Sub dari GitHub dengan meng-clone repositori Python lengkap.

  2. Di repositori yang di-clone, buka direktori samples/snippets. Anda dapat menyelesaikan langkah-langkah lainnya di direktori ini.

  3. Dari dalam direktori samples/snippets, instal dependensi yang Anda perlukan untuk menjalankan contoh:

    pip install -r requirements.txt
    
  4. Membuat topik:

     python publisher.py PUBSUB_PROJECT_ID create TOPIC_ID
    
  5. (Opsional) Jika Anda tidak memiliki endpoint push lokal untuk menguji langganan push di emulator, selesaikan langkah-langkah berikut untuk membuatnya dihttp://[::1]:3000/messages.

    1. Instal Server JSON.
      npm install -g json-server
      
    2. Mulai Server JSON.
      json-server --port 3000 --watch db.json
      
      dengan db.json berisi kode awal berikut:
      {
         "messages": []
      }
      
    3. Catat http://[::1]:3000/messages untuk PUSH_ENDPOINT di langkah berikutnya.
  6. Buat langganan ke topik:

    • Membuat langganan pull:

      python subscriber.py PUBSUB_PROJECT_ID create TOPIC_ID SUBSCRIPTION_ID
      
    • Membuat langganan push:

      python subscriber.py PUBSUB_PROJECT_ID create-push TOPIC_ID SUBSCRIPTION_ID \
      PUSH_ENDPOINT
      
  7. Memublikasikan pesan ke topik:

     python publisher.py PUBSUB_PROJECT_ID publish TOPIC_ID
    
  8. Baca pesan yang dipublikasikan ke topik:

    • Ambil pesan dari langganan pull Anda:

      python subscriber.py PUBSUB_PROJECT_ID receive SUBSCRIPTION_ID
      
    • Amati pesan yang dikirim ke endpoint push lokal Anda. Misalnya, pesan terlihat seperti berikut:

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

Mengakses variabel lingkungan

Dalam semua bahasa kecuali Java dan C#, jika Anda telah menetapkan PUBSUB_EMULATOR_HOST seperti yang dijelaskan dalam Menetapkan variabel lingkungan, library klien Pub/Sub akan otomatis memanggil API yang berjalan di instance lokal, bukan Pub/Sub.

Namun, library klien C# dan Java mengharuskan Anda mengubah kode untuk menggunakan emulator:

C#

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan C# di panduan memulai Pub/Sub menggunakan library klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API C# Pub/Sub.

Untuk melakukan autentikasi ke Pub/Sub, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.


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

Sebelum mencoba contoh ini, ikuti petunjuk penyiapan Java di panduan memulai Pub/Sub menggunakan library klien. Untuk mengetahui informasi selengkapnya, lihat dokumentasi referensi API Java Pub/Sub.

Untuk melakukan autentikasi ke Pub/Sub, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.


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

Menghentikan emulator

Untuk menghentikan emulator, tekan Control+C.

Setelah Anda menghentikan emulator, jalankan perintah berikut untuk menghapus variabel lingkungan PUBSUB_EMULATOR_HOST agar aplikasi Anda terhubung ke Pub/Sub:

Linux / macOS
unset PUBSUB_EMULATOR_HOST
Windows
set PUBSUB_EMULATOR_HOST=

Argumen command line emulator

Untuk mengetahui detail tentang argumen command line untuk emulator Pub/Sub, lihat gcloud beta emulators pubsub.

Fitur yang didukung

Emulator mendukung fitur Pub/Sub berikut:

  • Memublikasikan pesan
  • Menerima pesan dari langganan push dan pull
  • Mengurutkan pesan
  • Memutar ulang pesan
  • Meneruskan pesan ke topik yang dihentikan pengirimannya
  • Kebijakan coba lagi pada pengiriman pesan
  • Dukungan skema untuk Avro

Batasan umum

  • RPC UpdateTopic dan UpdateSnapshot tidak didukung.
  • Operasi IAM tidak didukung.
  • Retensi pesan yang dapat dikonfigurasi tidak didukung; semua pesan disimpan tanpa batas waktu.
  • Masa berlaku langganan tidak didukung. Masa berlaku langganan tidak akan habis.
  • Pemfilteran tidak didukung.
  • Dukungan skema untuk buffering protokol.
  • Langganan BigQuery dapat dibuat, tetapi tidak mengirim pesan ke BigQuery.
  • Mencari stempel waktu untuk langganan yang diurutkan tidak didukung.

Untuk melaporkan masalah, kirimkan Issue tracker publik.

Langkah selanjutnya

  • Untuk mempelajari cara menggunakan emulator Pub/Sub dengan minikube, lihat postingan blog ini.