יצירת מינוי עם SMT

במסמך הזה מוסבר איך ליצור מינוי ל-Pub/Sub עם Single Message Transforms (SMTs).

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

כדי ליצור מינוי עם SMT, אפשר להשתמש במסוף Cloud de Confiance , ב-Google Cloud CLI, בספריית הלקוח או ב-Pub/Sub API.

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

תפקידים והרשאות נדרשים

כדי לקבל את ההרשאות שנדרשות ליצירת מינוי עם SMT, צריך לבקש מהאדמין להקצות לכם את תפקיד ה-IAM‏ Pub/Sub Editor (roles/pubsub.editor) בפרויקט. כדי לקרוא הסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

זהו תפקיד שמוגדר מראש וכולל את ההרשאות שנדרשות ליצירת מינוי עם SMT. כדי לראות בדיוק אילו הרשאות נדרשות, אפשר להרחיב את הקטע ההרשאות הנדרשות:

ההרשאות הנדרשות

כדי ליצור מינוי עם SMT, צריך את ההרשאות הבאות:

  • נותנים הרשאה ליצור מינוי בפרויקט: pubsub.subscriptions.create

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

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

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

אפשר להגדיר בקרת גישה ברמת הפרויקט וברמת המשאב הספציפי.

יצירת מינוי עם SMT

לפני שיוצרים מינוי עם SMT, כדאי לעיין במסמכי התיעוד בנושא מאפיינים של מינוי.

כדי ליצור מינוי ל-Pub/Sub עם SMT אחד או יותר, מבצעים את השלבים הבאים. אפשר להפעיל עד 5 SMTs לכל מינוי.

המסוף

  1. נכנסים לדף Subscriptions של Pub/Sub במסוף Cloud de Confiance .

    לדף "מינויים"

  2. לוחצים על יצירת מינוי.

  3. בשדה מזהה מינוי, מזינים מזהה למינוי. מידע נוסף על מתן שמות למינויים זמין בהנחיות למתן שמות.

  4. בקטע טרנספורמציות, לוחצים על הוספת טרנספורמציה.

  5. בוחרים את סוג הטרנספורמציה. מידע נוסף על סוגי ה-SMT הנתמכים זמין במאמר סוגי SMT.

  6. קובעים את מאפייני ההגדרה של ה-SMT. קבוצת המאפיינים תלויה בסוג ה-SMT. מידע נוסף זמין במאמרי העזרה בנושא סוג ה-SMT הזה.

  7. זה שינוי אופציונלי. כדי לאמת את ה-SMT, לוחצים על אימות. אם ה-SMT תקין, מוצגת ההודעה "Validation passed". אחרת, תוצג הודעת שגיאה.

  8. כדי להוסיף עוד טרנספורמציה, לוחצים על הוספת טרנספורמציה וחוזרים על השלבים הקודמים.

    כדי לסדר את ה-SMT בסדר מסוים, לוחצים על העברה למעלה או על העברה למטה. כדי להסיר SMT, לוחצים על מחיקה.

  9. זה שינוי אופציונלי. כדי לבדוק SMT בהודעה לדוגמה, פועלים לפי השלבים הבאים:

    1. לוחצים על בדיקת טרנספורמציות.

    2. בחלון Test transform, בוחרים את הפונקציה שרוצים לבדוק.

    3. בחלון הזנת הודעה, מזינים הודעה לדוגמה.

    4. כדי להוסיף מאפיין להודעה, לוחצים על הוספת מאפיין ומזינים את המפתח והערך של המאפיין. אפשר להוסיף כמה מאפיינים.

    5. לוחצים על בדיקה. התוצאה של החלת ה-SMT על ההודעה מוצגת בקטע הודעת הפלט.

    6. כדי לסגור את החלון Test transforms, לוחצים על Close.

    אם יוצרים יותר מ-SMT אחד, אפשר לבדוק את כל רצף ההמרות באופן הבא:

    1. בודקים את ה-SMT הראשון ברצף, כמו שמתואר בשלבים הקודמים.
    2. בוחרים את ה-SMT הבא. הודעת הקלט מאוכלסת מראש עם הודעת הפלט מהבדיקה הקודמת.
    3. ממשיכים לבדוק את כללי ה-SMT לפי הסדר, כדי לוודא שכל הרצף פועל כמו שצריך.
  10. לוחצים על יצירה כדי ליצור את המינוי.

gcloud

  1. במסוף Cloud de Confiance , מפעילים את Cloud Shell.

    הפעלת Cloud Shell

    בחלק התחתון של Cloud de Confiance המסוף יתחיל סשן של Cloud Shell ותופיע הודעה של שורת הפקודה. Cloud Shell היא סביבת מעטפת שבה ה-CLI של Google Cloud מותקן ומוגדרים ערכים לפרויקט הקיים. הסשן יופעל תוך כמה שניות.

  2. יוצרים קובץ YAML או JSON שמגדיר SMT אחד או יותר. הגדרת ה-YAML או ה-JSON תלויה בסוג ה-SMT. מידע נוסף זמין במאמר בנושא סוגים של SMT.

    אם הקובץ כולל יותר מ-SMT אחד, ‏ Pub/Sub מבצע אותם לפי הסדר שבו הם מופיעים.

  3. זה שינוי אופציונלי. כדי לאמת SMT, מריצים את הפקודה gcloud pubsub message-transforms validate:

    gcloud pubsub message-transforms validate \
      --message-transform-file=TRANSFORM_FILE
    

    מחליפים את מה שכתוב בשדות הבאים:

    • TRANSFORM_FILE: הנתיב לקובץ YAML או JSON שמגדיר SMT יחיד. אם יוצרים כמה SMT, צריך לאמת כל אחד מהם בנפרד.
  4. זה שינוי אופציונלי. כדי לבדוק SMT אחד או יותר על הודעת Pub/Sub לדוגמה, מריצים את הפקודה gcloud pubsub message-transforms test:

    gcloud pubsub message-transforms test \
      --message-transforms-file=TRANSFORMS_FILE \
      --message=MESSAGE \
      --attribute=ATTRIBUTES
    

    מחליפים את מה שכתוב בשדות הבאים:

    • TRANSFORMS_FILE: הנתיב לקובץ YAML או JSON שמגדיר SMT אחד או יותר.
    • MESSAGE: גוף ההודעה לדוגמה.
    • ATTRIBUTES: אופציונלי. רשימה מופרדת בפסיקים של מאפייני הודעה. כל מאפיין הוא צמד מפתח/ערך בפורמט KEY="VALUE".

    הפקודה מפעילה את ה-SMT לפי הסדר, והפלט מכל SMT משמש כקלט ל-SMT הבא. הפקודה מחזירה את התוצאות של כל שלב.

  5. כדי ליצור את המינוי, מריצים את הפקודה gcloud pubsub subscriptions create:

    gcloud pubsub subscriptions create SUBSCRIPTION_ID \
        --topic=projects/PROJECT_ID/topics/TOPIC_ID \
        --message-transforms-file=TRANSFORMS_FILE
    

    מחליפים את מה שכתוב בשדות הבאים:

    • SUBSCRIPTION_ID: המזהה או השם של המינוי שרוצים ליצור. הנחיות למתן שמות למינויים מופיעות במאמר בנושא שמות משאבים. אי אפשר לשנות את השם של המינוי.

    • PROJECT_ID: מזהה הפרויקט שמכיל את הנושא.

    • TOPIC_ID: המזהה של הנושא להרשמה.

    • TRANSFORMS_FILE: הנתיב לקובץ YAML או JSON שמגדיר SMT אחד או יותר.

C#‎

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


using Google.Cloud.PubSub.V1;
using System;

public class CreateSubscriptionWithSingleMessageTransformSample
{
    public Subscription CreateSubscriptionWithSingleMessageTransform(string projectId, string topicId, string subscriptionId)
    {
        SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();
        TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);

        SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);
        MessageTransform removeSSNTransform = new MessageTransform
        {
            JavascriptUdf = new JavaScriptUDF
            {
                FunctionName = "redactSsn",
                Code = "function redactSsn(message, metadata) {"
                + "   const data = JSON.parse(message.data);"
                + "   delete data['ssn'];"
                + "   message.data = JSON.stringify(data);"
                + "   return message;"
                + "}"
            },
        };

        var subscription = subscriber.CreateSubscription(new Subscription
        {
            SubscriptionName = subscriptionName,
            TopicAsTopicName = topicName,
            MessageTransforms = { removeSSNTransform },
        });
        Console.WriteLine($"Subscription {subscription.Name} created with SMT.");

        return subscription;
    }
}

Java

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

import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
import com.google.pubsub.v1.JavaScriptUDF;
import com.google.pubsub.v1.MessageTransform;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.Subscription;
import java.io.IOException;

public class CreateSubscriptionWithSmtExample {
  public static void main(String... args) throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String topicId = "your-topic-id";
    String subscriptionId = "your-subscription-id";

    createSubscriptionWithSmtExample(projectId, topicId, subscriptionId);
  }

  public static void createSubscriptionWithSmtExample(
      String projectId, String topicId, String subscriptionId) throws IOException {

    // UDF that removes the 'ssn' field, if present
    String code =
        "function redactSSN(message, metadata) {"
            + "  const data = JSON.parse(message.data);"
            + "  delete data['ssn'];"
            + "  message.data = JSON.stringify(data);"
            + "  return message;"
            + "}";
    String functionName = "redactSSN";

    JavaScriptUDF udf =
        JavaScriptUDF.newBuilder().setCode(code).setFunctionName(functionName).build();
    MessageTransform transform = MessageTransform.newBuilder().setJavascriptUdf(udf).build();

    try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {

      ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);
      ProjectSubscriptionName subscriptionName =
          ProjectSubscriptionName.of(projectId, subscriptionId);

      Subscription subscription =
          subscriptionAdminClient.createSubscription(
              Subscription.newBuilder()
                  .setName(subscriptionName.toString())
                  .setTopic(topicName.toString())
                  // Add the UDF message transform
                  .addMessageTransforms(transform)
                  .build());

      System.out.println("Created subscription with SMT: " + subscription.getAllFields());
    }
  }
}

Python

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

from google.cloud import pubsub_v1
from google.pubsub_v1.types import JavaScriptUDF, MessageTransform

# TODO(developer): Choose an existing topic.
# project_id = "your-project-id"
# topic_id = "your-topic-id"
# subscription_id = "your-subscription-id"

publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
topic_path = publisher.topic_path(project_id, topic_id)
subscription_path = subscriber.subscription_path(project_id, subscription_id)

code = """function redactSSN(message, metadata) {
            const data = JSON.parse(message.data);
            delete data['ssn'];
            message.data = JSON.stringify(data);
            return message;
            }"""
udf = JavaScriptUDF(code=code, function_name="redactSSN")
transforms = [MessageTransform(javascript_udf=udf)]

with subscriber:
    subscription = subscriber.create_subscription(
        request={
            "name": subscription_path,
            "topic": topic_path,
            "message_transforms": transforms,
        }
    )
    print(f"Created subscription with SMT: {subscription}")

המשך

בדוגמה הבאה נעשה שימוש בגרסה הראשית של ספריית הלקוח Go Pub/Sub ‏ (v2). אם אתם עדיין משתמשים בספרייה v1, כדאי לעיין במדריך להעברה לגרסה v2. כדי לראות רשימה של דוגמאות קוד מגרסה 1, אפשר לעיין ב דוגמאות הקוד שהוצאו משימוש.

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

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/pubsub/v2"
	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb"
)

// createSubscriptionWithSMT creates a subscription with a single message transform function applied.
func createSubscriptionWithSMT(w io.Writer, projectID, topicID, subID string) error {
	// projectID := "my-project-id"
	// topicID := "my-topic"
	// subID := "my-sub"
	ctx := context.Background()
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("pubsub.NewClient: %w", err)
	}
	defer client.Close()

	code := `function redactSSN(message, metadata) {
			const data = JSON.parse(message.data);
			delete data['ssn'];
			message.data = JSON.stringify(data);
			return message;
		}`

	transform := &pubsubpb.MessageTransform{
		Transform: &pubsubpb.MessageTransform_JavascriptUdf{
			JavascriptUdf: &pubsubpb.JavaScriptUDF{
				FunctionName: "redactSSN",
				Code:         code,
			},
		},
	}

	sub := &pubsubpb.Subscription{
		Name:              fmt.Sprintf("projects/%s/subscriptions/%s", projectID, subID),
		Topic:             fmt.Sprintf("projects/%s/topics/%s", projectID, topicID),
		MessageTransforms: []*pubsubpb.MessageTransform{transform},
	}
	sub, err = client.SubscriptionAdminClient.CreateSubscription(ctx, sub)
	if err != nil {
		return fmt.Errorf("CreateSubscription: %w", err)
	}
	fmt.Fprintf(w, "Created subscription with message transform: %v\n", sub)
	return nil
}

איך מינויים עם תשלום חודשי משתלבים עם תכונות אחרות של מינויים

כשמשתמשים ב-SMT של מינוי, חשוב לזכור את הנקודות הבאות.

סינון

אם המינוי שלכם משתמש גם ב-SMT וגם במסננים מובנים של Pub/Sub, המסנן יופעל לפני ה-SMT. להגדרה הזו יש את ההשלכות הבאות:

  • אם ה-SMT משנה את מאפייני ההודעה, המסנן של Pub/Sub לא חל על קבוצת המאפיינים החדשה.
  • ה-SMT לא חל על הודעות שמסוננות על ידי המסנן Pub/Sub.
  • אם מסנני ה-SMTP שלכם מסננים הודעות, חשוב להיות מודעים להשפעה על מעקב אחרי הצטברות של בקשות הרשמה למינוי.
  • אם מחברים מינוי לפייפליין Dataflow, לא כדאי להשתמש במינוי SMT כדי לסנן הודעות, כי זה משבש את ההתאמה האוטומטית לעומס של Dataflow.

סדר ההודעות

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

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