עדכונים חיים ללא רענון עמוד: SSE, WebSocket, Polling
השקתם אתר מסחר אלקטרוני, והמנהלים שלכם מתלוננים על הצורך לרענן ידנית את סטטוסי ההזמנות. או שסוחרים מבזבזים שניות יקרות בלחיצה על F5 בהמתנה לציטוטי מחירים. עדכונים חיים הם כיום סטנדרט במסחר אלקטרוני, במסחר פיננסי וב-SaaS. אם המשתמשים שלכם מרעננים עמודים, אתם מפסידים המרות ויוצרים עומס מיותר על השרת. המהנדסים שלנו מיישמים מנגנוני זמן אמת, ובוחרים את הפרוטוקול האופטימלי לתשתית שלכם. עם ניסיון של 10+ שנים במערכות בעומס גבוה ו-50+ פריסות זמן אמת מוצלחות, אנחנו מספקים פתרונות שמחזירים את ההשקעה.
לפי מחקר של Google, עיכוב של 500 אלפיות שנייה מפחית המרות ב-20%. אנחנו משיגים זמן השהיה של פחות מ-100 אלפיות שנייה תחת 10,000 חיבורים מקבילים — מהיר פי 5 מ-Polling טיפוסי, משפרים את שביעות רצון המשתמשים ומפחיתים את עומס השרת ב-60% בהשוואה ל-Polling.
בהתאם לתרחיש, אנחנו בוחרים ב-SSE להתראות, ב-WebSocket להעברת נתונים דו-כיוונית, או ב-Long Polling כפתרון גיבוי. כל גרסה מותאמת למשימה ולארכיטקטורה הספציפית. צרו קשר עם המהנדסים שלנו לייעוץ חינמי להערכת הפרויקט שלכם.
למה Server-Sent Events (SSE) להתראות ועדכונים?
SSE הוא זרם חד-כיווני מהשרת על גבי HTTP סטנדרטי. הדפדפן מתחבר מחדש אוטומטית במקרה של ניתוק. אין צורך בהגדרת פרוטוקול נפרד, בניגוד ל-WebSocket. אידיאלי עבור:
- התראות על הזמנות חדשות, הודעות, התראות push;
- עדכוני פעילות חיים;
- התקדמות משימות (יצירת דוחות, עיבוד קבצים).
SSE פשוט פי 3 ליישום בתרחישים חד-כיווניים
SSE אינו דורש פורט נפרד. WebSocket מציע זמן השהיה נמוך פי 100 מ-Long Polling בעומס גבוה.איך לבחור בין SSE ל-WebSocket?
| טכנולוגיה | כיוון | תשתית | מתי להשתמש |
|---|---|---|---|
| SSE | שרת → לקוח | כל שרת HTTP | התראות, עדכונים, סטטוסים – ללא צורך בתקשורת דו-כיוונית |
| WebSocket | דו-כיווני | שרת WS + טיפול בחיבור מחדש | צ'אט, משחקים, עריכה שיתופית – הלקוח גם שולח נתונים |
| Polling | לקוח → שרת | כל תשתית | עדכונים נדירים (30–60 שניות), אב טיפוס |
| Long Polling | לקוח ↔ שרת | כל תשתית עם המתנה | גיבוי ל-SSE כאשר הלקוח אינו תומך ב-EventSource |
איך לעדכן את הממשק ללא הבהובים?
החלפת innerHTML גסה יוצרת חפצים. שתי גישות עובדות:
-
Morphdom — DOM-diff ללא Virtual DOM. השתמשו ב-
morphdomלעדכוני בלוקים חלקים תוך שמירה על אנימציות. - עדכוני מצב ב-React / Vue — פשוט עדכנו את המצב:
setOrders(prev => [data.order, ...prev]).
Server-Sent Events: יישום מאפס
SSE הוא תגובת HTTP עם Content-Type: text/event-stream. החיבור נשאר פתוח, והשרת דוחף אירועים. דוגמה ב-Node.js/Express:
app.get('/api/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no'); // Важно для nginx
const userId = req.user.id;
// Отправка начального состояния
res.write(`data: ${JSON.stringify({ type: 'init', unread: 5 })}\n\n`);
// Подписка на события
const unsubscribe = eventBus.subscribe(userId, (event) => {
res.write(`event: ${event.type}\n`);
res.write(`data: ${JSON.stringify(event.payload)}\n`);
res.write(`id: ${event.id}\n\n`); // для Last-Event-ID
});
// Keepalive каждые 30 секунд
const heartbeat = setInterval(() => {
res.write(': heartbeat\n\n');
}, 30000);
req.on('close', () => {
clearInterval(heartbeat);
unsubscribe();
});
});לקוח:
const evtSource = new EventSource('/api/events', { withCredentials: true, });
evtSource.addEventListener('notification', (e) => {
const data = JSON.parse(e.data);
showNotification(data);
});
evtSource.addEventListener('order-status', (e) => {
updateOrderStatus(JSON.parse(e.data));
});
// Браузер автоматически переподключается с Last-Event-ID
הגדרת Nginx עבור SSE
כדי ש-SSE יעבוד דרך פרוקסי, השביתו בופרטינג: app.get('/api/events', (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.setHeader('X-Accel-Buffering', 'no'); // Важно для nginx const userId = req.user.id; // Отправка начального состояния res.write(`data: ${JSON.stringify({ type: 'init', unread: 5 })}\n\n`); // Подписка на события const unsubscribe = eventBus.subscribe(userId, (event) => { res.write(`event: ${event.type}\n`); res.write(`data: ${JSON.stringify(event.payload)}\n`); res.write(`id: ${event.id}\n\n`); // для Last-Event-ID }); // Keepalive каждые 30 секунд const heartbeat = setInterval(() => { res.write(': heartbeat\n\n'); }, 30000); req.on('close', () => { clearInterval(heartbeat); unsubscribe(); }); }); ב-location, וגם הגדירו את הכותרת const evtSource = new EventSource('/api/events', { withCredentials: true, }); evtSource.addEventListener('notification', (e) => { const data = JSON.parse(e.data); showNotification(data); }); evtSource.addEventListener('order-status', (e) => { updateOrderStatus(JSON.parse(e.data)); }); // Браузер автоматически переподключается с Last-Event-ID . שלחו פעימות לב ריקות כל 15–30 שניות כדי למנוע מ-nginx לסגור את החיבור עקב פסק זמן.
WebSocket עם חיבור מחדש חכם
WebSocket טבעי אינו מתאושש מניתוקים. אנחנו כותבים wrapper עם backoff אקספוננציאלי:
class ReconnectingWebSocket {
constructor(url, protocols) {
this.url = url;
this.protocols = protocols;
this.reconnectDelay = 1000;
this.maxDelay = 30000;
this.listeners = new Map();
this.connect();
}
connect() {
this.ws = new WebSocket(this.url, this.protocols);
this.ws.onopen = () => {
this.reconnectDelay = 1000;
this.emit('open');
};
this.ws.onmessage = (e) => this.emit('message', JSON.parse(e.data));
this.ws.onclose = () => {
this.emit('close');
setTimeout(() => this.connect(), this.reconnectDelay);
this.reconnectDelay = Math.min(this.reconnectDelay * 1.5, this.maxDelay);
};
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
on(event, cb) {
if (!this.listeners.has(event)) this.listeners.set(event, []);
this.listeners.get(event).push(cb);
}
emit(event, data) {
this.listeners.get(event)?.forEach(cb => cb(data));
}
}או השתמשו בספריות מוכנות: reconnecting-websocket או socket.io (עם גיבוי מובנה ל-polling).
שידור באמצעות Redis Pub/Sub
עבור מספר שרתים (קנה מידה אופקי), אנחנו משתמשים ב-Redis כדי לשדר אירועים לכל החיבורים:
const redis = require('redis');
const publisher = redis.createClient();
const subscriber = redis.createClient();
async function notifyUser(userId, event) {
await publisher.publish(`user:${userId}`, JSON.stringify(event));
}
// subscriber.js (в том же процессе, что держит SSE/WS соединения)
await subscriber.subscribe(`user:${userId}`, (message) => {
const event = JSON.parse(message);
sseConnections.get(userId)?.forEach(res => {
res.write(`event: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`);
});
});
אופטימיזציה: עדכונים מצטברים לתדירויות גבוהות
עבור ציטוטי מניות או מדדים, אגרו אירועים בשרת ושלחו אצווה כל 100 אלפיות שנייה:
class UpdateBatcher {
constructor(flushInterval = 100) {
this.queue = new Map();
setInterval(() => this.flush(), flushInterval);
}
queue(userId, event) {
if (!this.queue.has(userId)) this.queue.set(userId, []);
this.queue.get(userId).push(event);
}
flush() {
this.queue.forEach((events, userId) => {
if (events.length) {
sendBatch(userId, events);
this.queue.set(userId, []);
}
});
}
}זה מפחית חבילות HTTP פי 10–50 ומוריד את עומס השרת.
תהליך יישום עדכונים בזמן אמת
- ניתוח דרישות ובחירת טכנולוגיה (SSE/WebSocket/Polling) עם עומס של עד 10,000 חיבורים.
- עיצוב ארכיטקטורה: זרימת נתונים, טיפול בשגיאות, קנה מידה עם Redis.
- יישום בצד השרת: SSE/WebSocket עם טיפול בחיבור מחדש.
- אינטגרציה בצד הלקוח: React/Vue/vanilla JS + ספריות (morphdom, EventSource).
- הגדרת Redis Pub/Sub לקנה מידה אופקי.
- בדיקות עומס: אימות עד 10,000 חיבורים מקבילים.
- תיעוד API, סכימת אירועים והדרכת צוות.
מה כלול בעבודה שלנו
- עיצוב ארכיטקטורה (בחירת טכנולוגיה, זרימת נתונים)
- יישום בצד השרת (SSE/WebSocket עם טיפול בשגיאות)
- אינטגרציה בצד הלקוח (React/Vue/vanilla JS)
- הגדרת Redis Pub/Sub לקנה מידה
- תיעוד (API, סכימת אירועים)
- בדיקות עומס (עד 10,000 חיבורים מקבילים)
- הדרכת צוות הלקוח
- תמיכה באחריות ל-12 חודשים
לוחות זמנים ועלויות משוערים
| תרחיש | מסגרת זמן | מחיר התחלתי |
|---|---|---|
| התראות SSE (הזמנות חדשות, הודעות) | 1–2 ימים | $500 |
| WebSocket עם חיבור מחדש ואינטגרציית React | 2–3 ימים | $1,200 |
| שידור באמצעות Redis Pub/Sub | בתוספת 1–2 ימים | $800 |
| עדכון זמן אמת מלא | 4–6 ימים | $2,500 |
המחיר עשוי להשתנות; צרו קשר להערכת פרויקט. החל מ-$500, הפתרונות שלנו מחזירים את ההשקעה על ידי הפחתת עומס השרת (חיסכון של עד 60% בתעבורה בהשוואה ל-Polling) והגדלת ההמרות ב-10–15% הודות לנתונים עדכניים. קבלו ייעוץ מהנדס.
בוחרים בנו בזכות הניסיון שלנו: 10+ שנים בפרויקטים בעומס גבוה, למעלה מ-50 פריסות מוצלחות של מערכות זמן אמת, מהנדסים מוסמכים. אנחנו מבטיחים יציבות בכל עומס.







