התראות WebSocket בזמן אמת לאתר שלך
תארו לעצמכם: משתמש מבצע הזמנה אך אינו מקבל עדכון סטטוס עד שהוא מרענן את הדף. או שמנהל אינו רואה תגובה חדשה עד לטעינה מחדש. זה לא רק אי-נוחות — זה אובדן המרות ואמון. אנחנו צוות מהנדסים עם ניסיון של 5+ שנים, המפתחים מערכות התראות מיידיות באמצעות WebSocket שמספקות אירועים במילישניות, ללא בקשות שרת מיותרות. ב-80+ פרויקטים, בנינו ארכיטקטורה אמינה שעומדת בעומסי שיא.
למה WebSocket במקום Polling?
עם Polling, הלקוח שואל את השרת כל N שניות. עם 10,000 משתמשים המבקשים סטטוס כל 5 שניות, השרת מקבל 120,000 בקשות בדקה — עומס עצום עם עיכוב של עד 5 שניות. WebSocket יוצר חיבור קבוע: הנתונים מגיעים באופן מיידי, והתעבורה מופחתת פי עשרה. אנו משתמשים ב-WebSocket לא רק לצ'אטים אלא גם להתראות סטטוס הזמנות, התראות מרקטפלייס, מערכות כרטוס, וכל תרחיש הדורש ראקטיביות.
אילו בעיות אנחנו פותרים
Polling מוגזם ועומס על השרת
מעבר ל-WebSocket מקצץ בקשות HTTP ממאות אלפים לכמה מאות בשעה. בפרויקט אחד, לאחר החלפת Polling ב-WebSocket, העומס על השרת ירד ב-80%, ועלויות התשתית נחתכו בחצי — חיסכון של כ-$2,400 בחודש (לפי שערי חליפין עדכניים).
מסירת התראות למשתמשים לא מקוונים
אם משתמש סוגר טאב אך עדיין רוצה לקבל התראות, אנו שומרים אותן במסד הנתונים ושולחים אותן בחיבור הבא. הפתרון שלנו משתמש ב-Redis Pub/Sub עם אחסון. בנוסף, אנו שולחים התראות Push דרך FCM/APNS. מסירה לא מקוונת עובדת עם עיכוב של לא יותר מ-100 אלפיות השנייה לאחר חיבור מחדש.
קנה מידה לאלפי חיבורים
יישום בודד יכול להתמודד עם עשרות אלפי חיבורי WebSocket. אנו מבצעים סקיילינג באמצעות Redis או Kafka כך שחיבורים עובדים על פני מספר מופעים. בדיקות עומס מאשרות יציבות עד 50,000 חיבורים מקבילים.
כיצד אנו מבטיחים מסירה למשתמשים לא מקוונים
בארכיטקטורה טיפוסית (ראה קוד למטה), אנו שומרים מיפוי של userId → set<socketId>. כאשר משתמש מתחבר, אנו בודקים אם יש התראות שלא נמסרו במסד הנתונים ומספקים אותן. אם המשתמש לא מקוון, ההתראה נשמרת עם סטטוס ממתין.
// notification-ws.service.ts
class NotificationWebSocketService {
private userSockets = new Map<string, Set<string>>();
async onConnect(socket: Socket, userId: string) {
if (!this.userSockets.has(userId)) {
this.userSockets.set(userId, new Set());
}
this.userSockets.get(userId)!.add(socket.id);
socket.join(`user:${userId}`);
const pending = await this.notificationRepo.findUndelivered(userId);
if (pending.length > 0) {
socket.emit('notifications:batch', pending);
await this.notificationRepo.markDelivered(pending.map(n => n.id));
}
}
async sendToUser(userId: string, notification: Notification): Promise<void> {
const isOnline = this.userSockets.has(userId) && this.userSockets.get(userId)!.size > 0;
if (isOnline) {
io.to(`user:${userId}`).emit('notification:new', notification);
await this.notificationRepo.markDelivered([notification.id]);
} else {
await this.notificationRepo.save({ ...notification, status: 'pending' });
await this.pushService.send(userId, notification);
}
}
} מדוע ה-React Hook // notification-ws.service.ts class NotificationWebSocketService { private userSockets = new Map<string, Set<string>>(); async onConnect(socket: Socket, userId: string) { if (!this.userSockets.has(userId)) { this.userSockets.set(userId, new Set()); } this.userSockets.get(userId)!.add(socket.id); socket.join(`user:${userId}`); const pending = await this.notificationRepo.findUndelivered(userId); if (pending.length > 0) { socket.emit('notifications:batch', pending); await this.notificationRepo.markDelivered(pending.map(n => n.id)); } } async sendToUser(userId: string, notification: Notification): Promise<void> { const isOnline = this.userSockets.has(userId) && this.userSockets.get(userId)!.size > 0; if (isOnline) { io.to(`user:${userId}`).emit('notification:new', notification); await this.notificationRepo.markDelivered([notification.id]); } else { await this.notificationRepo.save({ ...notification, status: 'pending' }); await this.pushService.send(userId, notification); } } } מפשט את האינטגרציה?
בצד הפרונטאנד, הכנו React Hook שמנווט לאירועי Socket.IO. הוא מטפל אוטומטית בהוספת התראות חדשות, ספירת לא-נקראות, וסימון כנקרא. כל מה שמפתח צריך לעשות הוא לקרוא ל-useNotifications() ולהציג את הרשימה.
// hooks/useNotifications.ts
function useNotifications() {
const [notifications, setNotifications] = useState<Notification[]>([]);
const [unreadCount, setUnreadCount] = useState(0);
const socket = useSocket();
useEffect(() => {
if (!socket) return;
socket.on('notification:new', (notification: Notification) => {
setNotifications(prev => [notification, ...prev]);
setUnreadCount(prev => prev + 1);
showToast(notification);
});
socket.on('notifications:batch', (batch: Notification[]) => {
setNotifications(prev => [...batch, ...prev]);
setUnreadCount(prev => prev + batch.filter(n => !n.readAt).length);
});
return () => {
socket.off('notification:new');
socket.off('notifications:batch');
};
}, [socket]);
const markAsRead = async (id: string) => {
await fetch(`/api/notifications/${id}/read`, { method: 'POST' });
setNotifications(prev => prev.map(n => n.id === id ? { ...n, readAt: new Date() } : n));
setUnreadCount(prev => Math.max(0, prev - 1));
};
const markAllAsRead = async () => {
await fetch('/api/notifications/read-all', { method: 'POST' });
setNotifications(prev => prev.map(n => ({ ...n, readAt: n.readAt || new Date() })));
setUnreadCount(0);
};
return { notifications, unreadCount, markAsRead, markAllAsRead };
} סוגי התראות והצגתן
אנו מגדירים אירועים טיפוסיים ליישום טיפוסי:
| סוג | תיאור | אייקון |
|---|---|---|
| order:status_changed | סטטוס ההזמנה השתנה | 📦 |
| message:received | הודעת צ'אט חדשה | 💬 |
| mention:comment | אזכור בתגובה | @ |
| task:assigned | משימה חדשה הוקצתה | ✅ |
| payment:processed | התשלום עובד | 💳 |
| system:alert | אזהרת מערכת | ⚠️ |
עבור כל סוג, ניתן להגדיר את משך התצוגה של ה-Toast ואת פעולת הלחיצה.
השוואה: Polling לעומת WebSocket
| פרמטר | Polling | WebSocket |
|---|---|---|
| זמן השהיה | 1–5 שניות | < 100 אלפיות השנייה |
| עומס על השרת | גבוה | נמוך |
| תעבורה | ~120,000 בקשות/דקה | ~1,000 הודעות/דקה |
| סקיילינג | קשה עם לקוחות רבים | קל עם Redis/Kafka |
מה כלול בעבודה
- תיעוד ארכיטקטוני: סכמת אינטראקציה, בחירת מחסנית (Socket.IO, Redis, PostgreSQL).
- יישום שירות צד שרת: מטפל WebSocket, אינטגרציית אימות, טיפול בניתוק.
- מודול פרונטאנד: React hook, רכיב פעמון, התראות Toast.
- אינטגרציית התראות Push (FCM/APNS) — אופציונלי.
- בדיקות עומס: אימות עד 50,000 חיבורים מקבילים.
- הוראות פריסה והדרכת צוות.
אנו מבטיחים פעולה יציבה בעומסי שיא — ניסיון של 5+ שנים בפתרונות בזמן אמת ו-80+ פרויקטים שהושלמו מדברים בעד עצמם. צרו קשר כדי לדון בפרויקט שלכם — נעזור לכם לבחור את הארכיטקטורה האופטימלית וליישם אותה במפתח מלא. קבלו ייעוץ עכשיו.
התהליך שלנו
- ניתוח — לימוד הארכיטקטורה הנוכחית, זיהוי תרחישי התראות והערכת עומס.
- עיצוב — בחירת פרוטוקול (WebSocket, SSE), תיווך הודעות (Redis, Kafka), סכמת אחסון.
- יישום — בניית צד שרת + פרונטאנד, כיסוי בבדיקות.
- אינטגרציה — חיבור לפרויקט קיים (Laravel, Nest.js, Django וכו').
- פריסה וניטור — הגדרת CI/CD, לוגים, התראות.
לוחות זמנים משוערים
יישום בסיסי (WebSocket + אחסון לא מקוון + React hook) — 7–10 ימים. עם התראות Push ובדיקות עומס — 2–3 שבועות. העלות מחושבת באופן אישי — כתבו לנו, נעריך את הפרויקט שלכם.







