הגדרת GCP Pub/Sub ברמת מומחה לתקשורת אמינה
תארו לעצמכם: שירות ההזמנות שלכם שולח אירוע, אבל שירות ההודעות לא מקבל אותו עקב timeout של RabbitMQ. הלקוח לא רואה אישור, וכסף אובד. עם הגדרה מקצועית של GCP Pub/Sub, זה לא יקרה—broker הודעות מנוהל מבטיח משלוח לפחות-פעם-אחת עם SLA של 99.95% ומתרחב למיליון הודעות בשנייה לכל topic ללא צורך בהקצאת משאבים. אנחנו משתמשים בו בסביבת production לפירוק microservices, צינורות CDC, ואירועי fan-out. במשך יותר מ-5 שנים, יישמנו יותר מ-50 פרויקטים עם Pub/Sub, תוך טיפול בעד 1M הודעות/שנייה. במקרה אחד, התפוקה גדלה מ-10K ל-500K הודעות/שנייה, בעוד עלויות התשתית ירדו ב-40%—וחסכו ללקוח כ-$5,000 בחודש. נקודה חשובה: Pub/Sub אינו תור FIFO; סדר ההודעות אינו מובטח (אלא אם כן מופעל message ordering). כפילויות יכולות להגיע—הפכו את ה-handlers שלכם ל-idempotent.
כיצד Google Pub/Sub פותר את בעיית המשלוח האמין
השירות משתמש במודל topic/subscription. publisher שולח הודעה ל-topic, ו-subscriber מקבל אותה דרך subscription (pull או push). משלוח לפחות-פעם-אחת מובטח: ההודעה תימסר אך עשויה להיות משוכפלת. תכננו את ה-handlers בהתאם.
מדוע אימות Schema הוא קריטי
אימות Schema דוחה הודעות שאינן תואמות לחוזה לפני שהן מגיעות ל-subscribers. אנו משתמשים בסכמות AVRO—הן קומפקטיות יותר מ-JSON ותומכות באבולוציה (הוספת שדות עם ברירות מחדל). ב-Terraform, הגדירו google_pubsub_schema ואפשרו schema_settings על ה-topic. אם הודעה נכשלת באימות schema, היא עוברת מיד ל-DLQ topic ללא ניסיונות עיבוד. זה מפחית את עומס הצרכנים ומפשט את תהליך הניפוי.
הגדרת GCP Pub/Sub: פרמטרי מפתח של Subscription
בעת הגדרת GCP Pub/Sub, חשוב לבחור ack deadline נכון—קצר מדי גורם לניסיונות חוזרים מיותרים, ארוך מדי גורם לעיכוב. אנו ממליצים על 60–120 שניות עבור handlers טיפוסיים.
דוגמת Terraform ל-topic עם DLQ
resource "google_pubsub_topic" "orders" {
project = var.project_id
name = "orders"
message_retention_duration = "604800s"
schema_settings {
schema = google_pubsub_schema.order.id
encoding = "JSON"
}
}
resource "google_pubsub_schema" "order" {
project = var.project_id
name = "order-schema"
type = "AVRO"
definition = file("schemas/order.avsc")
}
resource "google_pubsub_subscription" "orders_processor" {
project = var.project_id
name = "orders-processor"
topic = google_pubsub_topic.orders.id
ack_deadline_seconds = 60
message_retention_duration = "604800s"
retain_acked_messages = false
expiration_policy {
ttl = ""
}
retry_policy {
minimum_backoff = "10s"
maximum_backoff = "600s"
}
dead_letter_policy {
dead_letter_topic = google_pubsub_topic.orders_dlq.id
max_delivery_attempts = 5
}
}
resource "google_pubsub_topic" "orders_dlq" {
project = var.project_id
name = "orders-dlq"
message_retention_duration = "2592000s"
}מדיניות Dead Letter היא קריטית. בלעדיה, הודעת "רעל" (payload פגום שתמיד מפיל את ה-handler) תנוסה שוב ושוב ללא הגבלה, ותחסום הודעות אחרות. DLQ מיירט אותה לאחר 5 ניסיונות—תקבלו התראה ותוכלו לתקן את ה-payload.
| פרמטר | ברירת מחדל | המלצה |
|---|---|---|
| ack_deadline_seconds | 10 | 60–120 עבור handlers טיפוסיים |
| message_retention_duration | 7 ימים | הגדילו ל-30 אם נדרש ניתוח רטרוספקטיבי |
| max_delivery_attempts | 5 | 5–10 בהתאם לקריטיות |
| retry minimum_backoff | 10 שניות | כוונו לפי SLA |
| expiration_policy | אל תמחק | השאירו ריק עבור subscriptions קבועים |
עיבוד הודעות עם Python
from google.cloud import pubsub_v1
import json
def process_message(message: pubsub_v1.subscriber.message.Message):
try:
data = json.loads(message.data.decode("utf-8"))
order_id = data.get("order_id")
if not is_already_processed(order_id):
process_order(data)
mark_as_processed(order_id)
message.ack()
except Exception as e:
print(f"Error: {e}")
message.nack()
subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(PROJECT_ID, "orders-processor")
flow_control = pubsub_v1.types.FlowControl(max_messages=100)
streaming_pull_future = subscriber.subscribe(
subscription_path,
callback=process_message,
flow_control=flow_control,
)resource "google_pubsub_topic" "orders" { project = var.project_id name = "orders" message_retention_duration = "604800s" schema_settings { schema = google_pubsub_schema.order.id encoding = "JSON" } } resource "google_pubsub_schema" "order" { project = var.project_id name = "order-schema" type = "AVRO" definition = file("schemas/order.avsc") } resource "google_pubsub_subscription" "orders_processor" { project = var.project_id name = "orders-processor" topic = google_pubsub_topic.orders.id ack_deadline_seconds = 60 message_retention_duration = "604800s" retain_acked_messages = false expiration_policy { ttl = "" } retry_policy { minimum_backoff = "10s" maximum_backoff = "600s" } dead_letter_policy { dead_letter_topic = google_pubsub_topic.orders_dlq.id max_delivery_attempts = 5 } } resource "google_pubsub_topic" "orders_dlq" { project = var.project_id name = "orders-dlq" message_retention_duration = "2592000s" } מגביל את מספר ההודעות המעובדות במקביל. בלעדיו, יצרן מהיר יכול לרוקן את הזיכרון של הצרכן.
אבטחה: IAM וחשבונות שירות
gcloud pubsub topics add-iam-policy-binding orders \
--member=serviceAccount:[email protected] \
--role=roles/pubsub.publisher
gcloud pubsub subscriptions add-iam-policy-binding orders-processor \
--member=serviceAccount:[email protected] \
--role=roles/pubsub.subscriber ניטור והתראות
מדדים מרכזיים ב-Cloud Monitoring:
-
from google.cloud import pubsub_v1 import json def process_message(message: pubsub_v1.subscriber.message.Message): try: data = json.loads(message.data.decode("utf-8")) order_id = data.get("order_id") if not is_already_processed(order_id): process_order(data) mark_as_processed(order_id) message.ack() except Exception as e: print(f"Error: {e}") message.nack() subscriber = pubsub_v1.SubscriberClient() subscription_path = subscriber.subscription_path(PROJECT_ID, "orders-processor") flow_control = pubsub_v1.types.FlowControl(max_messages=100) streaming_pull_future = subscriber.subscribe( subscription_path, callback=process_message, flow_control=flow_control, )— גדל? הצרכן בפיגור. -
FlowControl(max_messages=100)— אם > ack_deadline, הודעות נמסרות מחדש. -
gcloud pubsub topics add-iam-policy-binding orders \ --member=serviceAccount:[email protected] \ --role=roles/pubsub.publisher gcloud pubsub subscriptions add-iam-policy-binding orders-processor \ --member=serviceAccount:[email protected] \ --role=roles/pubsub.subscriber— התראה על ערך שאינו אפס.
בעומס של 200K הודעות/שנייה, num_undelivered_messages צריך להיות קרוב לאפס. הגדרת התראות נכונה מפחיתה את MTTR ב-60% (לפי תיעוד Google Cloud Pub/Sub).
השוואה: Pub/Sub לעומת Cloud Tasks לעומת RabbitMQ
| תכונה | GCP Pub/Sub | Cloud Tasks | RabbitMQ (בניהול עצמי) |
|---|---|---|---|
| סוג משלוח | לפחות-פעם-אחת | לפחות-פעם-אחת | לכל-היותר-פעם-אחת (לפחות אפשרי) |
| סדר הודעות | לא ללא ordering | כן (FIFO) | כן (תור) |
| תפוקה מקסימלית | מיליונים/שנייה (~פי 10 מ-RabbitMQ) | ~5000/שנייה | ~100K/שנייה |
| אימות Schema | כן (AVRO/JSON) | לא | לא |
| תור הודעות מתות | מובנה | לא | דורש יישום מותאם |
Pub/Sub מנצח במהירות ובנוחות מנוהלה; Cloud Tasks כאשר נדרשים deduplication וסדר; RabbitMQ לפתרונות בניהול עצמי תחת שליטה קפדנית. לדוגמה, Pub/Sub מציע פי 10 תפוקה מ-RabbitMQ בקנה מידה גדול.
תהליך היישום ולוח זמנים
אנו עובדים בשלבים:
- ניתוח הארכיטקטורה ודרישות מודל האירועים.
- תכנון topics, subscriptions וסכמות.
- יישום מודולי Terraform עם פרמטרים (ack deadline, retry, DLQ).
- אינטגרציה עם צרכנים (pull/push).
- הגדרת ניטור והתראות.
- תיעוד runbooks והדרכת הצוות.
מה כלול בעבודה
כאשר אתם מזמינים הגדרת Pub/Sub turnkey, אתם מקבלים:
- Topics ו-subscriptions עם פרמטרים נכונים (ack deadline, retry, DLQ).
- אימות Schema להגנה מפני נתונים לא תקינים.
- תפקידי IAM וחשבונות שירות.
- קוד Terraform (מודולים) במאגר שלכם.
- לוחות מחוונים לניטור ב-Cloud Monitoring והתראות.
- תיעוד ארכיטקטורה ו-runbook.
- הדרכת צוות על idempotency וטיפול בשגיאות.
- תמיכה בהשקה (שבוע אחד).
לוח זמנים: טופולוגיה עם topic אחד ו-subscriptions — יום אחד. מערכות אירועים מורכבות עם topics מרובים, אימות schema ואינטגרציית push עם Cloud Run/Functions — 2–3 ימים. התמחור מחושב באופן אישי. עלות פרויקט טיפוסית: $2,000–$5,000, עם חיסכון שוטף של $5,000/חודש בתשתית.
מוכנים לארכיטקטורת אירועים אמינה? צרו קשר להערכה ראשונית של הפרויקט שלכם. הזמינו הגדרת Pub/Sub turnkey—אנו מבטיחים פעולה יציבה תחת כל עומס.
אנו ממליצים לקרוא את התיעוד הרשמי של Google Pub/Sub לפרטים נוספים.







