עודכן לפני חודש
ל-HTTP יש קצב בסיסי: בקשה, תגובה, סיום. הלקוח שואל, השרת עונה, החיבור נסגר. זה עובד נהדר לטעינת דפי אינטרנט, אבל יוצר בעיה ביישומים בזמן אמת. מה אם לשרת יש מה לומר והלקוח לא שואל?
אירועים שנשלחים מהשרת שוברים את הקצב הזה. השרת מגיב... ומוסיף לענות. החיבור נשאר פתוח. כאשר לשרת יש חדשות — מחיר מניה השתנה, הגיעה הודעה, גרסה הושלמה — הוא דוחף את החדשות דרך הצינור הפתוח. אין סקרים. אין שאלות. השרת מדבר כשיש לו מה לומר.
צורת הפתרון
דמיינו שאתם צופים בתוצאות בחירות. הדרך הישנה: הדפדפן שואל "יש עדכונים?" כל חמש שניות. השרת בדרך כלל אומר "לא." רוחב פס מבוזבז. השרת מוצף בבקשות. וכשהתוצאות כן משתנות, ייתכן שתצטרכו לחכות עד חמש שניות כדי לראות אותן.
SSE הופך את הגישה על פיה. הדפדפן שלכם פותח חיבור אחד ואומר "ספר לי כשמשהו קורה." השרת שומר על הקו הזה פתוח. כשהתוצאות משתנות, הוא מיד דוחף: "מחוז 7 דיווח זה עתה." אתם רואים את זה מיד. חיבור אחד. אין בקשות מיותרות. עדכונים מגיעים ברגע שנוצרים.
WebSockets פותר את זה גם, אבל הוא דו-כיווני — בנוי לאפליקציות צ'אט שבהן שני הצדדים מדברים כל הזמן. SSE פשוט יותר: זה פשוט HTTP שלא מנתק. פרוקסי, מאזני עומס ושכבות המטמון הקיימים שלכם כבר מבינים אותו.
איך זה עובד
הלקוח פותח חיבור:
זהו. שורה אחת להתחבר, מאזין אחד להודעות.
השרת שומר על החיבור פעיל וכותב אירועים כשהם קורים:
סוג התוכן text/event-stream אומר לדפדפן שזה SSE. שתי שורות חדשות (\n\n) מסמנות את סוף כל אירוע. כל השאר הוא פשוט HTTP.
פורמט האירוע
אירועי SSE הם טקסט רגיל עם מבנה פשוט:
data: נושא את המטען. שורות data: מרובות מאוחדות עם שורות חדשות.
event: מעניק שם לסוגי אירועים מותאמים. בלעדיו, אירועים מופעלים כ-"message."
id: מתייג אירועים לצורך התחברות מחדש. אם החיבור נפסק, הדפדפן אומר לשרת "הדבר האחרון ששמעתי היה 42" והשרת יכול לשחזר מה שפוספס.
retry: מציע עיכוב התחברות מחדש במילישניות.
הערות מתחילות בנקודותיים ושומרות על חיבורים פעילים דרך פרוקסי אגרסיביים:
התחברות מחדש אוטומטית
כאן SSE מצטיין בשקט.
כשחיבור נפסק — הפרעה ברשת, הפעלה מחדש של שרת, מחשב נייד שמתעורר משינה — הדפדפן מתחבר מחדש אוטומטית. אין צורך בקוד. זה פשוט עובד.
יותר מזה: אם לאירועים שלכם היו מזהים, הדפדפן שולח Last-Event-ID: 42 בהתחברות מחדש. השרת שלכם יכול לשחזר אירועים שפוספסו. ניתוקים קצרים לא גורמים לאובדן נתונים.
ברירת המחדל לניסיון חוזר היא 3 שניות. שרתים יכולים לשנות זאת לכל חיבור בנפרד עם השדה retry:.
סוגי אירועים מותאמים
ליישומים אמיתיים יש סוגים שונים של עדכונים:
השרת שולח אירועים עם סוג:
לכל סוג יש מאזין משלו. הפרדה נקייה.
היכן SSE מצטיין
לוחות מחוונים וניטור. מדדי שרת, תקינות יישומים, סטטוס מערכת — אלה זורמים בכיוון אחד. SSE דוחף עדכונים ברגע שהם זמינים.
התראות. הודעות חדשות, אזכורים, התראות. השרת יודע מתי משהו קורה ומודיע לכם מיד.
עדכונים חיים. חדשות, תוצאות ספורט, עדכוני מדיה חברתית. תוכן מופיע ברגע שהוא מתפרסם.
מעקב אחר התקדמות. העלאת קבצים, יצירת דוחות, עבודות אצווה. דחפו אחוז השלמה במקום לשאול על הסטטוס.
צפייה שיתופית. מספר אנשים שצופים באותם נתונים יכולים לראות עדכונים בו-זמנית. (שיתוף פעולה מלא עם עריכה בדרך כלל דורש WebSockets.)
המגבלות
כיוון אחד בלבד. SSE הוא משרת ללקוח. לקוחות שולחים נתונים דרך בקשות HTTP רגילות (POST, PUT). זה בדרך כלל מספיק — רוב האפליקציות זקוקות להרבה עדכונים מהשרת אבל לפעולות לקוח מזדמנות בלבד.
שישה חיבורים לדומיין. ב-HTTP/1.1, דפדפנים מגבילים חיבורים מקבילים. חיבור SSE אחד לדומיין ה-API שלכם משאיר חמישה לכל השאר. HTTP/2 פותר את זה, אבל כדאי לדעת.
טקסט בלבד. נתונים בינאריים צריכים קידוד Base64. לסטרימינג וידאו או קבצים גדולים, זה מוסיף תקורה.
ללא Internet Explorer. Edge תומך בו. Chrome, Firefox, Safari תומכים בו. IE מעולם לא תמך. פוליפילים קיימים אבל מוסיפים מורכבות.
SSE מול WebSockets
בחרו SSE כאשר:
- עדכונים זורמים בעיקר משרת ללקוח
- אתם רוצים פשטות מקסימלית
- תשתית HTTP סטנדרטית חשובה (פרוקסי, CDN, מאזני עומס)
- התחברות מחדש אוטומטית עם שחזור הודעות בעלת ערך
בחרו WebSockets כאשר:
- שני הצדדים שולחים הודעות תכופות
- חביון מלקוח לשרת חשוב (משחקים, עריכה שיתופית)
- אתם צריכים נתונים בינאריים גולמיים
- אתם כבר מנהלים תשתית WebSocket
יישומים רבים משתמשים בשניהם: SSE לשטף הבלתי פוסק של עדכוני שרת, HTTP POST רגיל לפעולת לקוח מזדמנת.
אבטחה
SSE הוא פשוט HTTP, אז חלה אבטחה סטנדרטית.
אימות: עוגיות או טוקנים עובדים כרגיל. ה-constructor של EventSource מקבל withCredentials לעוגיות בין מקורות שונים.
הרשאות: אמתו הרשאות כשהחיבור נפתח. אל תשלחו אירועים שמשתמש לא אמור לראות.
CORS: SSE בין מקורות שונים דורש כותרות מתאימות. Access-Control-Allow-Origin וחבריה.
HTTPS: השתמשו בו. wss:// ל-WebSockets, https:// ל-SSE. אותה הצפנה, אותם אישורים.
סקלאביליות
כל חיבור SSE הוא חיבור HTTP פתוח שצורך זיכרון שרת. בקנה מידה גדול, זה משמעותי.
מגבלות חיבור: דעו כמה השרתים שלכם מסוגלים לטפל. תכננו קיבולת בהתאם למשתמשים מקבילים בשיא.
סקלאביליות אופקית: אם משתמשים מתחברים לשרתים שונים, אירועים חייבים להגיע לכולם. Redis Pub/Sub או מתווכי הודעות דומים מפיצים אירועים בכל הצי שלכם.
סשנים דביקים: לאחר ההתחברות, משתמשים צריכים להישאר באותו שרת (או להתנתק ולהתחבר מחדש בצורה חלקה).
פעימות לב: שלחו הערות תקופתיות (: ping) כדי לשמור על חיבורים פעילים דרך פרוקסי שמסיימים חיבורים סרק.
ניפוי שגיאות
כלי הפיתוח של הדפדפן מציגים SSE בלשונית Network. אפשר לצפות באירועים שמגיעים בזמן אמת, לראות כותרות חיבור ולזהות ניתוקים.
ל-EventSource יש מאפיין readyState:
0= מתחבר1= פתוח2= סגור
שאלות נפוצות על אירועים שנשלחים מהשרת
האם אפשר לשלוח נתונים מלקוח לשרת עם SSE?
לא. SSE הוא חד-כיווני — משרת ללקוח בלבד. לתקשורת מלקוח לשרת, השתמשו בבקשות HTTP סטנדרטיות (fetch, POST, PUT). זהו העיצוב המכוון: SSE מטפל בכיוון ה"דחיפה" בעוד בקשות רגילות מטפלות בכיווני ה"משיכה" וה"שליחה".
מה קורה אם חיבור ה-SSE שלי נפסק?
הדפדפן מתחבר מחדש אוטומטית. אם האירועים שלכם כללו מזהים, הוא שולח את המזהה האחרון שהתקבל לשרת, שיכול לשחזר אירועים שפוספסו. אין צורך לכתוב לוגיקת התחברות מחדש — היא מובנית ב-API של EventSource.
במה SSE שונה מ-long polling?
Long polling פותח בקשה, ממתין לנתונים, מקבל אותם, סוגר, ואז פותח בקשה חדשה. כל תגובה דורשת חיבור חדש. SSE פותח חיבור אחד ושומר אותו פתוח לאורך זמן, כאשר השרת כותב אירועים מרובים על פני אותו חיבור. SSE יעיל יותר ובעל חביון נמוך יותר.
האם SSE עובד דרך פרוקסי ארגוניים וחומות אש?
בדרך כלל כן, מכיוון שזה HTTP סטנדרטי. פרוקסי אגרסיביים מסוימים מאגדים תגובות או מסיימים חיבורים סרק. שליחת הערות פעימות לב תקופתיות (: ping) שומרת על חיבורים פעילים. חיבורי HTTPS פחות סבירים להיות מושפעים.
מתי כדאי להשתמש ב-SSE במקום WebSockets?
כשעדכונים זורמים בעיקר משרת ללקוח. SSE פשוט יותר לממש, עובד עם תשתית HTTP קיימת, כולל התחברות מחדש מובנית, ואינו דורש תוכנת שרת מיוחדת. השתמשו ב-WebSockets כשאתם צריכים תקשורת דו-כיוונית תכופה או נתונים בינאריים ללא תקורת קידוד.
האם דף זה היה מועיל?