במסמך הזה מפורטים טיפים נפוצים לפתרון בעיות במינויים מסוג pull ב-Pub/Sub. מידע נוסף על מינויים מסוג pull זמין במדריך למנויים מסוג pull.
כדי לעקוב ביעילות אחרי מינוי Pub/Sub, מומלץ קודם לבדוק את ציון תקינות השהייה של המסירה (subscription/delivery_latency_health_score) כדי לראות אילו גורמים יכולים לתרום להשהיה בלתי צפויה או מוגברת.
הגיל של ההודעה הכי ישנה שלא נשלח אישור על קבלתה ממשיך לעלות
המדד oldest_unacked_message_age הוא מדד חשוב למעקב אחרי תקינות המינויים ב-Pub/Sub. המדד הזה מודד את הגיל, בשניות, של ההודעה הכי ישנה בפיגור של מינוי שלא קיבלה עדיין אישור (ACK) ממנוי. המדד הזה מספק תובנות חשובות לגבי צווארי בקבוק או עיכובים אפשריים בעיבוד.
מעקב אחרי הצטברות הודעות מבטיח עיבוד יעיל של ההודעות בזמן. מעקב אחרי הגיל של ההודעה הכי ישנה שלא נשלח לגביה אישור יכול לעזור לכם לזהות מראש מצבים שבהם הצרכנים לא עומדים בקצב. השיטה הזו מאפשרת התערבות מוקדמת כדי לפתור בעיות פוטנציאליות שקשורות לירידה בביצועים.
אלה כמה בעיות נפוצות ב-backlog שכדאי לבדוק:
בעיות בהגדרת לקוח
אם יש עלייה בו-זמנית במדדים oldest_unacked_message_age ו-num_undelivered_messages, יכול להיות שהמנויים לא עומדים בקצב של נפח ההודעות. במצב כזה, כדאי להתמקד ברכיבי המינוי:
תקינות הלקוח: ניתוח של ניצול המשאבים במחשבים שמארחים לקוחות של מינויים, כמו מעבד (CPU), זיכרון ורוחב פס ברשת. כדאי לחפש נקודות לחץ שעשויות לפגוע ביעילות העיבוד.
קוד לקוח: כדאי לבדוק שינויים שנעשו לאחרונה בקוד ולעיין ביומני השגיאות. באגים או חוסר יעילות בקוד של המנוי יכולים להשפיע באופן משמעותי על קצב עיבוד ההודעות. שימו לב שיכול להיות שיש בעיות בהודעות ספציפיות. לדוגמה, יכול להיות שכמה הודעות יצטרכו לגשת לאותה שורה במסד נתונים בו-זמנית. ההתנהגות הזו עלולה לגרום למחלוקות ולזמן אחזור גבוה.
מגבלות על מכסות: צריך לוודא שלא חרגתם ממכסות או ממגבלות של Pub/Sub שהוטלו על ידי שירות האירוח שלכם. אם המנויים מתארחים ב- Google Cloud, כדאי לבדוק את המכסות של משאבי Compute Engine או GKE כדי למנוע צווארי בקבוק פוטנציאליים.
המשתמש שרשום לניוזלטר שלח אישור שלילי להודעות
כשלקוח רשום שולח אישור שלילי (NACK) להודעה, הוא מאותת ל-Pub/Sub שההודעה לא עברה עיבוד בהצלחה. לאחר מכן, מערכת Pub/Sub מנסה לשלוח מחדש את אותה הודעה. אם מתקבלים אישורים חוזרים על אי-קבלת הודעה, נוצרים כפילויות ועלול להיות עיכוב משמעותי בשליחת ההודעה.
שימו לב: שליחת NACK להודעה לא מבטיחה שההודעה הבאה שתתקבל תהיה שונה. יכול להיות שמדיניות המסירה מחדש של Pub/Sub תמשיך למסור מחדש הודעות עם NACK לפני הודעות חדשות. לכן, אל תסתמכו על NACK כשיטה לסינון או לדילוג על הודעות ספציפיות. במקום זאת, כדאי להגדיר מדיניות ניסיון חוזר, ועדיף השהיה מעריכית לפני ניסיון חוזר (exponential backoff), כדי להשהות הודעות בודדות שסביר להניח שניתן יהיה לעבד אותן מאוחר יותר, אבל צריך להמתין קצת יותר זמן לפני העברה חוזרת.
אם אתם צריכים לדלג בכוונה על הודעות מסוימות, הגישה המומלצת היא לשלוח אישור (ACK) להודעות האלה, גם אם לא תעבדו אותן. כך הם יוסרו מהמינוי, לא יתבצעו מסירות חוזרות מיותרות ותצומצם צריכת המשאבים. השארת הודעות ללא אישור, בין אם בכוונה ובין אם לא, יוצרת בעיות של הצטברות הודעות ומשלוחים כפולים.
זמן אחזור ארוך של מסירה
השהיית המסירה ב-Pub/Sub היא משך הזמן שנדרש להודעה ממוציא לאור להגיע למנוי. בקטעים הבאים מפורטות כמה סיבות אפשריות לזמן חביון גבוה של מסירת הודעות.
אין מספיק מנויים
כדי להשיג זמן אחזור נמוך באופן עקבי, לקוחות שמשתמשים ב-StreamingPull צריכים לשמור על כמה חיבורי StreamingPull פתוחים למינוי שלהם. בלי חיבורים פעילים של אפליקציות רשומות, מערכת Pub/Sub לא יכולה להעביר הודעות במהירות. זרם אחד יכול להיות נקודת כשל בודדת, מה שמגדיל את הסיכון לעיכובים. המדד subscription/open_streaming_pulls מאפשר לראות את מספר החיבורים הפעילים לסטרימינג. כדאי להשתמש בנתון הזה כדי לוודא שיש לכם מספיק זרמים באופן עקבי לטיפול בהודעות נכנסות.
לקוחות שמשתמשים ב-unary pull צריכים לשמור על כמה בקשות pull פתוחות במינוי כדי להשיג חביון נמוך באופן עקבי. יכול להיות שבקשות לא תכופות יגרמו להצטברות הודעות ב-backlog ולהגדלת זמן האחזור. הגישה הזו עוזרת לצמצם את הפערים בקישוריות ולשפר את זמן האחזור של המסירה.
מומלץ להשתמש בספריית הלקוח ברמה גבוהה במקרים שבהם נדרשת תפוקה גבוהה וזמן אחזור נמוך עם תקורה תפעולית מינימלית ועלות עיבוד מינימלית. כברירת מחדל, ספריית הלקוח ברמה גבוהה משתמשת ב-StreamingPull API, כי בדרך כלל הוא בחירה טובה יותר לצמצום זמן האחזור. ספריות הלקוח ברמה גבוהה מכילות פונקציות וסיווגים מוכנים מראש שמטפלים בקריאות ה-API הבסיסיות לאימות, לאופטימיזציה של קצב העברת הנתונים והחביון, לפורמט ההודעות ולתכונות אחרות.
בעיות בהגדרת לקוח
High backlog
חשוב לזכור שפיגור בהודעות של הודעות שלא אושרו במינוי ל-Pub/Sub מגדיל באופן מובנה את זמן האחזור מקצה לקצה, כי המנויים לא מעבדים את ההודעות באופן מיידי.
הזמנת מפתחות ומסירה של כל פריט בדיוק פעם אחת
תכונות כמו מפתחות הזמנה ואספקה מדויקת של פעם אחת הן חשובות, אבל הן דורשות תיאום נוסף ב-Pub/Sub כדי להבטיח אספקה נכונה. התיאום הזה יכול להפחית את הזמינות ולהגדיל את זמן האחזור. ההבדל בין המצבים מינימלי, אבל כל שלב תיאום שנדרש עלול לגרום לעלייה זמנית בזמן האחזור או בשיעור השגיאות. אם ההזמנה מופעלת, אי אפשר למסור הודעות עם מפתח הזמנה עד שההודעות הקודמות עם אותו מפתח הזמנה יאושרו.
כדאי לשקול אם סדר ההודעות או מסירה של כל הודעה בדיוק פעם אחת הם חיוניים לאפליקציה שלכם. אם השהיה הנמוכה היא בראש סדר העדיפויות שלכם, צמצום השימוש בתכונות האלה יכול לעזור להפחית את העיכובים בעיבוד ההודעות.
הגדלת גודל ההודעה
עלייה פתאומית בגודל ההודעה עלולה להאריך את זמן ההעברה בין Pub/Sub לבין הלקוח, ולהאט את זמן העיבוד של ההודעות בצד הלקוח.
אם אתם מבחינים בעלייה בזמן האחזור של המסירה, אתם יכולים לבדוק את גודל ההודעות באמצעות המדד topic/message_sizes, ולבצע קיבוץ לפי topic_id. בודקים אם יש קשר בין העליות החדות בגודל ההודעות לבין בעיות בביצועים.
הודעות חסרות
אם אתם חושדים שההודעות לא מועברות בהצלחה למנוי, יכול להיות שאחת מהסיבות הבאות היא הגורם לכך.
הפצת הודעות במינויים ל-Pub/Sub עם כמה צרכנים
ב-Pub/Sub, יכול להיות שההודעות יחולקו באופן לא אחיד בין הצרכנים באותו מינוי. מערכת Pub/Sub מבצעת איזון עומסים של הודעות בין כל הלקוחות הפעילים, אבל המטרה העיקרית היא למקסם את נפח ההודעות הכולל שעוברות עיבוד ולמזער את העומס, ולא להבטיח חלוקה שווה לחלוטין. המערכת מפנה באופן דינמי יותר הודעות לצרכנים שמציגים קיבולת גבוהה יותר – אלה שמאשרים הודעות במהירות ולא מוגבלים על ידי הגדרות בקרה על זרימת נתונים שלהם. צרכנים שמבצעים עיבוד של הודעות במהירויות שונות או בתנאים שונים (למשל, זמינות משאבים, זמן אחזור ברשת) כנראה יטפלו בכמויות שונות של הודעות. בדרך כלל, צרכנים מהירים יותר שמגיבים מהר יותר יקבלו ויעבדו חלק גדול יותר מעומס ההודעות.
שיטת ההפצה הזו בין כמה צרכנים אומרת שהסדר שבו ההודעות מתקבלות ומעובדות יכול להיות שונה. לכן, אלא אם הזמנת ההודעות מופעלת במינוי ובעלי התוכן הדיגיטלי כוללים מפתחות הזמנה, אין ערובה לכך שהצרכנים יעבדו את ההודעות בסדר שבו הן פורסמו.
שימו לב: יכול להיות שכבר יש הודעות שממתינות ללקוחות, וצבר של הודעות שלא אושרו לא בהכרח אומר שתקבלו את ההודעות האלה בבקשת המשיכה הבאה. חשוב לדעת שצרכן יכול להיות מישהו שמשתמש במשיכה במסוף Google Cloud או ב-Google Cloud CLI, או מישהו שמריץ מנוי מותאם אישית באופן מקומי כדי לבדוק הודעות.
במקרים של לקוחות unary Pull, יכול להיות שתראו כמה בקשות pull שמחזירות אפס הודעות. כמו שצוין בקטע לא מספיק מנויים, מומלץ לשמור על כמה בקשות משיכה פתוחות, כי יכול להיות שבחלק מהבקשות יוחזרו פחות מהמספר המקסימלי של ההודעות שהוגדר, או אפילו אפס הודעות, גם אם יש הצטברות של הודעות. הסיבה לכך היא שצרכנים אחרים עשויים להחזיק בהסכמי שכירות על ההודעות הזמינות.
אם צרכן לא מאשר קבלה של הודעה לפני תום המועד לאישור, או אם הוא שולח אישור שלילי (NACK) לגבי ההודעה, מערכת Pub/Sub תנסה לשלוח אותה מחדש. אפשר לנסות לשלוח מחדש לכל צרכן פעיל במינוי, לאו דווקא לצרכן שקיבל את ההודעה בהתחלה. לכן, יכול להיות שמזהה הודעה מסוים יימסר לכמה צרכנים שונים שמחוברים למינוי במהלך חייו, וכל אחד מהם ינסה לעבד אותו, עד שאחד מהם יאשר את קבלתו.
אם אתם חושדים בהתנהגויות לא צפויות של הפצת הודעות, כדאי לבדוק אם יש כמה צרכנים שמחוברים למינוי בו-זמנית, ולבדוק את מדדי הביצועים וההגדרות שלהם בנפרד.
סינון לפי המינוי
בודקים אם למינוי מצורף מסנן. במקרה כזה, תקבלו רק את ההודעות שתואמות למסנן. שירות Pub/Sub מאשר באופן אוטומטי את ההודעות שלא תואמות למסנן. חשוב להבין איך מסננים משפיעים על מדדי העומס.
שימוש באפשרות returnImmediately
אם הלקוח משתמש ב-Pull unary, צריך לבדוק אם השדה returnImmediately מוגדר לערך true. זהו שדה שהוצא משימוש, שמורה לשירות Pub/Sub להגיב לבקשת המשיכה באופן מיידי, גם אם לא מוחזרות הודעות. כתוצאה מכך, יכול להיות שבקשות משיכה יחזרו עם 0 הודעות גם אם יש עומס.
בעיות בהגדרת לקוח
אם אתם משתמשים בספריית הלקוח של Java ומאתחלים את המנוי שלכם באמצעות ערוץ gRPC מותאם אישית באמצעות השיטה setChannelProvider(), אתם צריכים לוודא שההגדרה maxInboundMessageSize היא לפחות 20MB (בהתאם לערך ברירת המחדל של הספרייה) כשאתם יוצרים את TransportChannelProvider. אם הערך הזה קטן מ-10MB, לא ניתן יהיה לקבל כראוי הודעות שגדולות מ-maxInboundMessageSize. שיטות נפוצות להגדרת ההגדרה הזו הן InstantiatingGrpcChannelProvider.Builder.setMaxInboundMetadataSize() ו-ManagedChannelBuilder.maxInboundMetadataSize().
התמודדות עם כפילויות
שכפול הודעות ב-Pub/Sub קורה בדרך כלל כשמנויים לא יכולים לאשר קבלת הודעות לפני תום המועד לאישור קבלה. כתוצאה מכך, ההודעות נשלחות מחדש ונוצר הרושם של כפילויות. אפשר למדוד את שיעור המנויים שלא עומדים בדדליין לאישור באמצעות המדד subscription/expired_ack_deadlines_count. מידע נוסף על מעקב אחרי המועד האחרון לאישור
כדי להפחית את שיעור הכפילות, כדאי להאריך את המועדים האחרונים לשליחת הודעות.
- ספריות הלקוח מטפלות בהארכת המועד האחרון באופן אוטומטי, אבל יש מגבלות ברירת מחדל על המועד האחרון המקסימלי להארכה שאפשר להגדיר.
- אם אתם יוצרים ספריית לקוח משלכם, אתם יכולים להשתמש בשיטה
modifyAckDeadlineכדי להאריך את המועד האחרון לאישור.
אם ההודעות נמשכות אל המנוי מהר יותר ממה שהמנוי יכול לעבד ולאשר, יכול להיות שחלק מההודעות יפוג תוקפן ויהיה צורך להאריך את המועד האחרון שלהן. עם זאת, אם העומס על המנוי יישאר גבוה, בסופו של דבר לא יעזרו דחיות חוזרות של מועדי היעד. בתרחיש הכי גרוע, זה יכול להוביל לכך שמנוי יקבל כמות גדולה של עותקים כפולים, מה שיחמיר את הבעיה של הצטברות בקשות. כפילויות שפג תוקפן ואז נוצרות כפילויות חדשות.
כדי לא להעמיס על המנוי, כדאי להקטין את מספר ההודעות שהמנוי מושך בכל פעם. כך המנוי צריך לעבד פחות הודעות עד למועד האחרון. פחות הודעות יפוג תוקפן ופחות הודעות יישלחו מחדש.
כדי להקטין את מספר ההודעות שהמנוי מושך בכל פעם, צריך להקטין את ההגדרה של המספר המקסימלי של הודעות ממתינות בהגדרות בקרה על זרימת נתונים של המנוי. אין ערך שמתאים לכולם, ולכן צריך להתאים את המגבלה המקסימלית של הודעות בהמתנה על סמך קצב העברת הנתונים והקיבולת של המנויים. חשוב לזכור שכל אפליקציה מעבדת הודעות בצורה שונה, ומשך הזמן שנדרש לאישור קבלה של הודעה משתנה מאפליקציה לאפליקציה.
כפיית ניסיונות חוזרים
כדי לאלץ את Pub/Sub לנסות שוב לשלוח הודעה, שולחים בקשת nack. אם אתם לא משתמשים בספריות לקוח ברמה גבוהה, אתם יכולים לשלוח בקשת modifyAckDeadline עם ackDeadlineSeconds שמוגדר ל-0.
סידור המקשים
כשמערכת Pub/Sub מעבירה מחדש הודעה עם מפתח סדר, היא מעבירה מחדש גם את כל ההודעות הבאות עם אותו מפתח סדר, גם אם הן אושרו בעבר. הפעולה הזו מתבצעת כדי לשמור על סדר הרצף. עם זאת, אין ערובה מוחלטת לכך שהודעות תלויות יישלחו רק אחרי מעקב מוצלח של הודעות קודמות ברצף.
המנוי שולח הודעות NACK על ההודעות
המינוי לא מאשר את קבלת ההודעות
פתרון בעיות במינוי StreamingPull
הקשר בין מדד זמן האחזור של הבקשה לבין זמן האחזור הכולל של המסירה
ב-StreamingPull, המדד serviceruntime.googleapis.com/api/request_latencies מייצג את משך הזמן שבו הסטרים פתוח. המדד הזה לא עוזר לקבוע את זמן האחזור של המסירה מקצה לקצה.
במקום להשתמש במדד זמן האחזור של הבקשה, כדאי להשתמש בציון הבריאות של זמן האחזור של המסירה כדי לבדוק אילו גורמים תורמים לעלייה בזמן האחזור הכולל של המסירה.
חיבורי StreamingPull נסגרים עם סטטוס שאינו OK
סטרימינג משיכה תמיד נסגר עם סטטוס שאינו OK. בניגוד לסטטוס שגיאה של קריאות RPC יחידות, הסטטוס הזה של StreamingPull הוא רק אינדיקציה לכך שהזרם נותק. הבקשות לא נכשלות. לכן, יכול להיות שב-StreamingPull API יהיה שיעור שגיאות מפתיע של 100%, אבל ההתנהגות הזו היא מכוונת.
מכיוון שזרמי StreamingPull תמיד נסגרים עם שגיאה, לא מומלץ לבדוק מדדים של סיום הזרם בזמן אבחון שגיאות. במקום זאת, כדאי להתמקד במדד התגובה StreamingPull subscription/streaming_pull_response_count, שמקובץ לפי response_code או response_class.
מחפשים את השגיאות הבאות:
שגיאות מסוג Failed precondition יכולות להתרחש אם יש הודעות בפיגור של המינוי שמוצפנות באמצעות מפתח Cloud KMS מושבת. כדי להמשיך את המשיכה, צריך לשחזר את הגישה למפתח.
שגיאות של חוסר זמינות יכולות להתרחש כש-Pub/Sub לא מצליח לעבד בקשה. הסיבה לכך היא כנראה מצב זמני, וספריית הלקוח מנסה שוב לשלוח את הבקשות. אם אתם משתמשים בספריית לקוח, לא נדרשת פעולה מצדכם.
שגיאות מסוג 'לא נמצא' יכולות להתרחש אם המינוי נמחק או אם הוא מעולם לא היה קיים. המקרה האחרון קורה אם סיפקתם נתיב מינוי לא תקין.