בדיקת אפליקציות באופן מקומי באמצעות האמולטור

כדי לפתח ולבדוק את האפליקציה באופן מקומי, אפשר להשתמש באמולטור Pub/Sub, שמספק אמולציה מקומית של שירות הייצור של Pub/Sub. מריצים את האמולטור של Pub/Sub באמצעות Google Cloud CLI.

כדי להריץ את האפליקציה באמולטור, קודם מפעילים את האמולטור ומגדירים את משתני הסביבה. האפליקציה צריכה לתקשר עם האמולטור במקום עם שירות Pub/Sub בסביבת הייצור. המשאבים שנוצרו וההודעות שפורסמו באמולטור נשמרים למשך משך החיים של סשן האמולטור.

לפני שמתחילים

לפני שמשתמשים באמולטור Pub/Sub, צריך להשלים את התנאים המוקדמים הבאים:

התקנת האמולטור

מתקינים את האמולטור משורת הפקודה:

gcloud components install pubsub-emulator
gcloud components update

התקנת האמולטור כקובץ אימג' של קונטיינר

כדי להתקין ולהריץ את האמולטור כקונטיינר, מורידים ומתקינים את קובץ אימג' של Docker של gCloud.

הפעלת האמולטור

מפעילים את האמולטור על ידי הפעלת pubsub start משורת פקודה. לפני שמריצים את הפקודה, מחליפים את PUBSUB_PROJECT_ID במחרוזת שלCloud de Confiance מזהה פרויקט תקף. המחרוזת לא צריכה לייצג פרויקט אמיתי כי האמולטור של Pub/Sub פועל באופן מקומי. Cloud de Confiance

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

gcloud beta emulators pubsub start רשימה מלאה של הדגלים

אחרי שמפעילים את האמולטור, מוצגת הודעה שדומה להודעה הבאה:

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

ההודעה הזו מציינת ששרת Pub/Sub פועל בנקודת הקצה של האמולטור במחשב המקומי שלכם במקום בנקודת הקצה Cloud de Confiance by S3NS . כל הפעולות מתבצעות באופן מקומי, כולל הפעולות הבאות:

  • יצירת נושא או מינוי
  • הוצאה לאור
  • הרשמה

הגדרת משתני סביבה

אחרי שמפעילים את האמולטור, צריך להגדיר את משתני הסביבה כדי שהאפליקציה תתחבר לאמולטור במקום ל-Pub/Sub. מגדירים את משתני הסביבה האלה באותו מחשב שבו מריצים את האפליקציה.

צריך להגדיר את משתני הסביבה בכל פעם שמפעילים את האמולטור. משתני הסביבה תלויים במספרי יציאות שמוקצים באופן דינמי, ויכולים להשתנות כשמפעילים מחדש את האמולטור.

הגדרה אוטומטית של המשתנים

אם האפליקציה והאמולטור פועלים באותה מכונה, אפשר להגדיר את משתני הסביבה באופן אוטומטי:

‫Linux / macOS

מריצים את הפקודה env-init באמצעות החלפת פקודות:

$(gcloud beta emulators pubsub env-init)

Windows

יצירה והרצה של קובץ אצווה באמצעות פלט מ-env-init:

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

האפליקציה שלכם תתחבר עכשיו לאמולטור Pub/Sub.

הגדרה ידנית של המשתנים

אם האפליקציה והאמולטור פועלים במכונות שונות, צריך להגדיר את משתני הסביבה באופן ידני:

  1. מריצים את הפקודה env-init:

     gcloud beta emulators pubsub env-init

  2. במחשב שבו האפליקציה פועלת, מגדירים את משתנה הסביבה PUBSUB_EMULATOR_HOST ואת הערך שלו בהתאם להוראות בפלט של הפקודה env-init. ההגדרה הזו מחברת את האפליקציה לאמולטור. אפשר גם להגדיר את משתנה הסביבה PUBSUB_PROJECT_ID לפרויקט שבו רוצים להשתמש באמולטור.

    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

האפליקציה שלכם תתחבר עכשיו לאמולטור Pub/Sub.

הערה: אם אתם משתמשים בשרת הפיתוח המקומי של Python App Engine Standard, אתם צריכים להעביר את משתנה הסביבה הזה בשורת הפקודה באופן הבא:

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

dev_appserver.py כלול ב[PATH_TO_CLOUD_SDK]/google-cloud-sdk/bin/dev_appserver.py.

שימוש באמולטור

כדי להשתמש באמולטור, צריך אפליקציה שנבנתה באמצעות ספריות הלקוח של Cloud. האמולטור לא תומך בפקודות של Cloud de Confiance מסוף או gcloud pubsub.

בדוגמה הבאה מוצג שימוש באמולטור ובאפליקציה שמשתמשת בספריית הלקוח של Python Cloud כדי לבצע פעולות שונות. דוגמאות לפעולות האלה כוללות יצירת נושא, פרסום הודעות וקריאת הודעות.

במחשב שבו הגדרתם את משתני הסביבה של האמולטור, מבצעים את השלבים הבאים:

  1. כדי לקבל את הדוגמאות של Python ל-Pub/Sub מ-GitHub, צריך לשכפל את מאגר Python המלא.

  2. במאגר המשוכפל, עוברים לספרייה samples/snippets. את שאר השלבים מבצעים בספרייה הזו.

  3. בספרייה samples/snippets, מתקינים את הרכיבים התלויים שצריך כדי להריץ את הדוגמה:

    pip install -r requirements.txt
    
  4. כדי ליצור נושא:

     python publisher.py PUBSUB_PROJECT_ID create TOPIC_ID
    
  5. (אופציונלי) אם אין לכם נקודת קצה מקומית של הודעות פוש לבדיקת מינויים להודעות פוש באמולטור, צריך לבצע את השלבים הבאים כדי ליצור אחת ב-http://[::1]:3000/messages.

    1. מתקינים את JSON Server.
      npm install -g json-server
      
    2. מפעילים את JSON Server.
      json-server --port 3000 --watch db.json
      
      כאשר db.json מכיל את קוד לתחילת הדרך הבא:
      {
         "messages": []
      }
      
    3. חשוב לרשום את http://[::1]:3000/messages בשביל PUSH_ENDPOINT בשלב הבא.
  6. יוצרים מינוי לנושא:

    • יצירת מינוי שליפה:

      python subscriber.py PUBSUB_PROJECT_ID create TOPIC_ID SUBSCRIPTION_ID
      
    • יצירת מינוי דחיפה:

      python subscriber.py PUBSUB_PROJECT_ID create-push TOPIC_ID SUBSCRIPTION_ID \
      PUSH_ENDPOINT
      
  7. פרסום הודעות בנושא:

     python publisher.py PUBSUB_PROJECT_ID publish TOPIC_ID
    
  8. קוראים את ההודעות שפורסמו בנושא:

    • אחזור הודעות ממינוי השליפה שלך:

      python subscriber.py PUBSUB_PROJECT_ID receive SUBSCRIPTION_ID
      
    • בודקים את ההודעות שנמסרו לנקודת הקצה המקומית של הודעות הפוש. לדוגמה, הודעות שנראות כך:

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

גישה למשתני סביבה

בכל השפות חוץ מ-Java ו-C#, אם הגדרתם את PUBSUB_EMULATOR_HOST כמו שמתואר במאמר הגדרת משתני סביבה, ספריות הלקוח של Pub/Sub קוראות אוטומטית ל-API שפועל במופע המקומי ולא ל-Pub/Sub.

עם זאת, בספריות הלקוח של C# ‎ ו-Java צריך לשנות את הקוד כדי להשתמש באמולטור:

C#

לפני שמנסים את הדוגמה הזו, צריך לפעול לפי C#הוראות ההגדרה במאמר התחלה מהירה של Pub/Sub באמצעות ספריות לקוח. מידע נוסף מופיע במאמרי העזרה של Pub/Sub C# API.

כדי לבצע אימות ב-Pub/Sub, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך 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

לפני שמנסים את הדוגמה הזו, צריך לפעול לפי Javaהוראות ההגדרה במאמר התחלה מהירה של Pub/Sub באמצעות ספריות לקוח. מידע נוסף מופיע במאמרי העזרה של Pub/Sub Java API.

כדי לבצע אימות ב-Pub/Sub, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך 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();
    }
  }
}

הפסקת האמולטור

כדי לעצור את האמולטור, מקישים על Control+C.

אחרי שמפסיקים את האמולטור, מריצים את הפקודה הבאה כדי להסיר את משתנה הסביבה PUBSUB_EMULATOR_HOST, כך שהאפליקציה תתחבר ל-Pub/Sub:

Linux / macOS
unset PUBSUB_EMULATOR_HOST
Windows
set PUBSUB_EMULATOR_HOST=

ארגומנטים בשורת הפקודה של האמולטור

פרטים על ארגומנטים של שורת הפקודה לאמולטור Pub/Sub מופיעים במאמר gcloud beta emulators pubsub.

תכונות נתמכות

האמולטור תומך בתכונות הבאות של Pub/Sub:

  • פרסום הודעות
  • קבלת הודעות ממינויים מסוג push ו-pull
  • סדר ההודעות
  • הפעלה מחדש של הודעות
  • העברת הודעות לנושאים להודעות ללא מוצא
  • מדיניות ניסיון חוזר בנושא מסירת הודעות
  • תמיכה בסכימה ב-Avro
  • סינון

מגבלות ידועות

  • אין תמיכה ב-RPC‏ UpdateTopic וב-RPC‏ UpdateSnapshot.
  • אין תמיכה בפעולות IAM.
  • אין תמיכה בהגדרה של משך השמירה של ההודעות, וכל ההודעות נשמרות ללא הגבלת זמן.
  • אין תמיכה בתפוגה של מינוי. המינויים לא פוקעים.
  • תמיכה בסכימה של מאגרי פרוטוקולים.
  • אפשר ליצור מינויים ל-BigQuery, אבל לא לשלוח הודעות ל-BigQuery.
  • אי אפשר לדלג לנקודת זמן במינויים מסודרים.
  • אפשר ליצור נושאים ומינויים באמצעות Single Message Transforms (SMTs), אבל ההודעות לא יומרו.

כדי לדווח על בעיות, שולחים דיווח בכלי הציבורי למעקב אחר בעיות.

המאמרים הבאים