בדף הזה מוסבר איך להפעיל WebSockets או שירותי סטרימינג אחרים ב-Cloud Run, ואיך לכתוב לקוחות לשירותים כאלה.
אפליקציות WebSockets נתמכות ב-Cloud Run בלי צורך בהגדרות נוספות. עם זאת, הסטרימינג של WebSockets הוא בקשות HTTP, שעדיין כפופות לזמן הקצוב לתפוגה של בקשות שהוגדר לשירות Cloud Run, ולכן צריך לבצע את הפעולות הבאות:
- מגדילים את הזמן הקצוב לתפוגה של הבקשה למשך הזמן המקסימלי שבו רוצים להשאיר את הסטרימינג של WebSockets פתוח, למשל 60 דקות.
- מוודאים שהלקוחות יכולים להתחבר מחדש.
- כדאי להשתמש בזיקה לסשן (session affinity) כדי שהלקוחות יתחברו מחדש לאותו מכונה ככל האפשר.
- אל תפעילו את האפשרות HTTP/2 end-to-end.
למרות שהזיקה לסשן (session affinity) ב-Cloud Run מספקת את הזיקה הטובה ביותר, בקשות חדשות של WebSockets עדיין יכולות להתחבר למכונות שונות, בגלל איזון העומסים המובנה. כדי לפתור את הבעיה, צריך לסנכרן את הנתונים בין המכונות.
שימו לב שגם WebSockets ב-Cloud Run נתמכים אם אתם משתמשים ב-Cloud Load Balancing.
פריסת שירות WebSockets לדוגמה
אתם יכולים להשתמש ב-Cloud Shell כדי לפרוס במהירות שירות לדוגמה של לוח מחיק, שמשתמש ב-WebSockets עם Cloud Run: פריסת דוגמה
לחלופין, אם רוצים לפרוס את שירות הלוח הלבן לדוגמה באופן ידני:
משכפלים את המאגר של Socket.IO באופן מקומי באמצעות כלי שורת הפקודה של git:
git clone https://github.com/socketio/socket.io.gitעוברים לספריית הדוגמה:
cd socket.io/examples/whiteboard/פורסים שירות חדש ב-Cloud Run על ידי פיתוח השירות מקוד המקור באמצעות Google Cloud CLI:
gcloud run deploy whiteboard --allow-unauthenticated --source=.אחרי פריסת השירות, פותחים שתי כרטיסיות נפרדות בדפדפן ועוברים לכתובת ה-URL של השירות. כל מה שתציירו בכרטיסייה אחת אמור להופיע בכרטיסייה השנייה (ולהפך), כי הלקוחות מחוברים לאותו מופע דרך WebSockets.
מדריך מלא לדוגמה של צ'אט ב-WebSockets
אם אתם רוצים הסבר מלא על הקוד, דוגמאות קוד נוספות זמינות בנושא מדריך ליצירת שירות צ'אט של WebSocket ל-Cloud Run.
שיטות מומלצות
החלק הכי קשה ביצירת שירותי WebSockets ב-Cloud Run הוא סנכרון הנתונים בין כמה מכונות של Cloud Run. זה קשה בגלל ההתאמה האוטומטית לעומס (auto-scaling) והאופי חסר המצב (stateless) של המכונות, ובגלל המגבלות על בו-זמניות וזמן קצוב לתפוגה של בקשות.
טיפול בפסקי זמן קצובים לתפוגה של בקשות ובחיבורים מחדש של לקוחות
בקשות WebSockets מטופלות כבקשות HTTP ארוכות ב-Cloud Run. הם כפופים לזמני קצובים לתפוגה של בקשות (כרגע עד 60 דקות, כברירת מחדל 5 דקות), גם אם שרת האפליקציה לא אוכף זמנים קצובים לתפוגה.
לכן, אם הלקוח משאיר את החיבור פתוח למשך זמן ארוך יותר מזמן הקצוב לתפוגה שנדרש ומוגדר לשירות Cloud Run, הלקוח ינותק כשהזמן הקצוב לתפוגה של הבקשה יסתיים.
לכן, לקוחות WebSockets שמתחברים ל-Cloud Run צריכים לטפל בחיבור מחדש לשרת אם הזמן הקצוב לתפוגה של הבקשה חלף או אם השרת מתנתק. כדי לעשות את זה בלקוחות מבוססי-דפדפן, אפשר להשתמש בספריות כמו reconnecting-websocket או לטפל באירועי "ניתוק" אם משתמשים בספרייה SocketIO.
חיובים שנוצרים כשמשתמשים ב-WebSockets
מכונה של Cloud Run שיש לה חיבור WebSocket פתוח כלשהו נחשבת לפעילה, ולכן מוקצה לה מעבד (CPU) והשירות מחויב כחיוב מבוסס-מכונה.
מקסימום בו-זמניות (concurrency)
שירותי WebSockets בדרך כלל מיועדים לטפל בהרבה חיבורים בו-זמנית. מכיוון ש-Cloud Run תומך בחיבורים בו-זמניים (עד 1,000 לכל קונטיינר), Google ממליצה להגדיל את הערך המקסימלי של הגדרת הבו-זמניות של הקונטיינר לערך גבוה יותר מברירת המחדל, אם השירות שלכם יכול להתמודד עם העומס באמצעות המשאבים הנתונים.
מידע על סשנים קבועים (זיקה לסשן)
מכיוון שחיבורי WebSockets הם בעלי מצב (stateful), הלקוח יישאר מחובר לאותו קונטיינר ב-Cloud Run לאורך כל משך החיבור. באופן טבעי, זה מאפשר שמירה על הסשן בהקשר של חיבור WebSocket יחיד.
כדי להשתמש בכמה חיבורי WebSockets ובחיבורים עוקבים, אתם יכולים להגדיר את שירות Cloud Run כך שישתמש בזיקה לסשן (session affinity), אבל הזיקה הזו היא במאמץ מרבי, כך שעדיין יכול להיות שבקשות WebSockets יגיעו למכונות שונות. יכול להיות שלקוחות שמתחברים לשירות Cloud Run יקבלו שירות ממכונות שונות שלא מתואמות או משתפות נתונים.
כדי לצמצם את הבעיה, צריך להשתמש במאגר נתונים חיצוני כדי לסנכרן את המצב בין מכונות Cloud Run, כפי שמוסבר בקטע הבא.
סנכרון נתונים בין מכונות
צריך לסנכרן את הנתונים כדי לוודא שהלקוחות שמתחברים לשירות Cloud Run מקבלים את אותם הנתונים מהחיבור ל-WebSockets.
לדוגמה, נניח שאתם בונים שירות של חדר צ'אט באמצעות WebSockets ומגדירים את מספר הבקשות המקסימלי בו-זמנית ל-1,000. אם יותר מ-1,000 משתמשים יתחברו לשירות הזה בו-זמנית, הם יקבלו שירות ממכונות שונות, ולכן הם לא יוכלו לראות את אותן ההודעות בחדר הצ'אט.
כדי לסנכרן נתונים בין המכונות של Cloud Run, למשל כדי לקבל את ההודעות שפורסמו בחדר צ'אט מכל המכונות, צריך מערכת חיצונית לאחסון נתונים, כמו מסד נתונים או תור הודעות.
אם אתם משתמשים במסד נתונים חיצוני כמו Cloud SQL, אתם יכולים לשלוח הודעות למסד הנתונים ולבצע דגימה ממסד הנתונים מדי פעם. עם זאת, חשוב לזכור שלמכונות של Cloud Run אין מעבד (CPU) כשהקונטיינר לא מטפל בבקשות. אם השירות שלכם מטפל בעיקר בבקשות WebSockets, למאגר יוקצה מעבד כל עוד יש לפחות לקוח אחד שמחובר אליו.
תורי הודעות פועלים טוב יותר לסנכרון נתונים בין קונטיינרים של Cloud Run בזמן אמת, כי תורי ההודעות החיצוניים לא יכולים לפנות לכל מכונה כדי "לדחוף" נתונים. השירותים צריכים "למשוך" הודעות חדשות מתור ההודעות על ידי יצירת חיבור לתור ההודעות.
Google ממליצה להשתמש במערכות חיצוניות של תור הודעות, כמו Redis Pub/Sub (Memorystore) או עדכונים בזמן אמת של Firestore, שיכולות להעביר עדכונים לכל המכונות דרך חיבורים שהופעלו על ידי מכונת הקונטיינר.
שימוש ב-Redis Pub/Sub
אתם יכולים להשתמש במנגנון Redis Pub/Sub על ידי יצירת מכונה של Redis מ-Memorystore. אם אתם משתמשים בספריית Socket.IO ל-WebSockets, אתם יכולים להשתמש במתאם redis שלה.
בארכיטקטורה הזו שמבוססת על Redis, כל מכונה של Cloud Run יוצרת חיבור לטווח ארוך לערוץ Redis שמכיל את ההודעות שהתקבלו (באמצעות הפקודה SUBSCRIBE). ברגע שהמופעים של הקונטיינר מקבלים הודעה חדשה בערוץ, הם יכולים לשלוח אותה ללקוחות שלהם דרך WebSockets בזמן אמת.
באופן דומה, כשלקוח פולט הודעה באמצעות WebSockets, המכונה שמקבלת את ההודעה מפרסמת אותה בערוץ Redis (באמצעות הפקודה PUBLISH), ומכונות אחרות שמנויות לערוץ הזה יקבלו את ההודעה.
אם אתם רוצים הסבר מלא על הקוד, דוגמאות קוד נוספות זמינות בנושא מדריך ליצירת שירות צ'אט של WebSocket ל-Cloud Run.