يېڭىلاندى 1 month ago
ל-HTTP יש חוסר התאמה בסיסי עם שיחה אנושית: אפשר לדבר רק כשמדברים אליך.
ב-HTTP, הלקוח שואל והשרת עונה. ואז שתיקה. אם לשרת יש משהו חדש לומר — הגיעה הודעת צ'אט, מחיר מניה השתנה, שחקן אחר זז — הוא צריך לחכות. הוא לא יכול ליזום. הוא יכול רק להגיב כשנשאל.
זה יוצר את בעיית התקשורת בזמן אמת.
הפתרונות הזמניים (ולמה הם נכשלים)
Polling הוא הפתרון בכוח גס: לשאול כל כמה שניות אם משהו השתנה. "יש הודעות חדשות?" "לא." "יש הודעות חדשות?" "לא." "יש הודעות חדשות?" "כן, הנה אחת." זה מבזבז רוחב פס, שורף משאבי שרת, ומכניס זמן השהייה — אתה מגלה על עדכונים רק במרווחי ה-polling.
Long polling הוא יותר חכם. השרת מחזיק את הבקשה שלך כבת ערובה עד שמשהו קורה, ואז עונה. אתה מיד שולח בקשה נוספת. תמיד ממתינה בקשה אחת. אבל עדיין יש מחזורי בקשה-תגובה, ויוצרים עומס עבור כל הודעה.
Server-Sent Events מאפשרים לשרתים לדחוף ללקוחות — אבל רק לשרתים. אם הלקוח צריך לשלוח משהו, חוזרים לבקשות HTTP רגילות. רחובות חד-סטריים בעולם שזקוק לשיחה.
WebSockets פותרים את זה על ידי יצירת חיבור מתמשך ודו-כיווני. כל צד יכול לשלוח הודעות מתי שרוצה. ללא בקשת רשות. ללא המתנה לתורך.
לחיצת היד: HTTP מאתחל את החלפתו שלו
WebSockets מבצעים תרגיל אלגנטי: הם משתמשים ב-HTTP כדי ליצור משהו שאינו HTTP.
הלקוח שולח מה שנראה כבקשת HTTP רגילה, אך עם כותרות מיוחדות:
השרת מגיב:
"101 Switching Protocols" — החיבור עובר שינוי באמצע הדרך. אותו חיבור TCP שהתחיל לדבר HTTP מדבר עכשיו WebSocket. שיחת ה-HTTP הסתיימה; פרוטוקול חדש תופס את מקומה.
זו גאונות פרגמטית. WebSockets רוכבים על תשתית HTTP קיימת דרך חומות אש ו-proxies, ואז מורידים את העור הזה ברגע שהם בפנים.
פרוטוקול הקו
הודעות WebSocket עוברות כמסגרות — כותרות קטנות (2–14 בתים) ואחריהן מטען.
מסגרות טקסט נושאות מחרוזות UTF-8. JSON נמצא כאן.
מסגרות בינאריות נושאות בתים גולמיים. תמונות, שמע, פרוטוקולים בינאריים.
מסגרות בקרה מנהלות את החיבור עצמו. Ping שואל "האם אתה חי?" Pong עונה "כן." Close מתחיל כיבוי מסודר.
Masking הוא דרישת אבטחה להודעות מלקוח לשרת. המטען עובר XOR עם מסיכה אקראית כדי למנוע התקפות הרעלת מטמון. הודעות מהשרת ללקוח מדלגות על זה — שרתים נחשבים אמינים.
הודעות גדולות יכולות להתפצל על פני מספר מסגרות, כדי למנוע ממסירה מסיבית אחת לחסום הודעות קטנות ודחופות.
מה WebSockets מאפשרים
צ'אט הוא הדוגמה הקנונית. הודעות מופיעות מיידית כי השרת דוחף אותן ברגע שמגיעות — ללא עיכוב polling, ללא בקשות מבוזבזות.
עריכה שיתופית ב-Google Docs או ב-Figma. כל הקשה, כל תנועת סמן, מסונכרנת בין משתמשים בזמן אמת.
משחקים דורשים דו-כיווניות עם זמן השהייה נמוך. הפעולות שלך מגיעות לשרת מהר; תנועות שחקנים אחרים מגיעות אליך מהר.
לוחות מחוונים חיים מציגים מדדים, סטטוס והתראות כשהם קורים. הנתונים נדחפים אליך.
פלטפורמות מסחר שבהן אלפיות השנייה חשובות. עדכוני מחירים זורמים ברצף; פקודות מאושרות מיידית.
התראות שנמסרות ברגע שנוצרות, לא בפעם הבאה שאתה מבצע poll.
ממשק API בצד הלקוח
ממשק ה-WebSocket API של JavaScript פשוט באופן מרענן:
ארבעה אירועים. מתודת שליחה אחת. מתודת סגירה אחת. זה כל השטח.
מציאות צד השרת
לכל שפה עיקרית יש ספריות WebSocket:
- Node.js: ws (מינימלי), socket.io (עם כל הסוללות), uWebSockets (ביצועים)
- Python: websockets, aiohttp, Django Channels
- Go: gorilla/websocket
- Java: javax.websocket, Spring WebSocket
- Ruby: ActionCable
שרתים מטפלים בלחיצת היד, עוקבים אחר לקוחות מחוברים, מנתבים הודעות ומנקים ניתוקים.
תבניות הודעות
שידור: שליחה לכולם. הודעת צ'אט הולכת לכל חברי החדר.
ממוקד: שליחה לאחד. הודעה פרטית מגיעה רק לנמען שלה.
חדרים/ערוצים: קיבוץ לקוחות לוגית. שדר ל-"room-123" במקום לכולם.
בקשה-תגובה: שכב RPC מעל. כלול מזהה הודעה; התאם תגובות לפי מזהה.
Pub/Sub: לקוחות נרשמים לנושאים, מקבלים רק את מה שביקשו.
אתגר ההתרחבות
WebSockets הם בעלי מצב. כל חיבור מחזיק זיכרון, צורך מתאר קובץ, שומר הקשר. זה שובר את חוסר-המצב היפה של HTTP שהפך את ההתרחבות לקלה.
אם משתמש A מחובר לשרת 1 ומשתמש B מחובר לשרת 2, כיצד הודעתו של A מגיעה ל-B?
מתווכי הודעות פותרים את זה. Redis Pub/Sub, RabbitMQ או Kafka יושבים בין שרתים. שרת 1 מפרסם; שרת 2 נרשם ומעביר. כל שרת מדבר עם כל שרת אחר דרך המתווך.
Sticky sessions שומרות משתמשים על אותו שרת, מפשטות ניתוב אך יוצרות נקודות חמות.
מגבלות חיבור חשובות. דע כמה חיבורים בו-זמניים התשתית שלך מטפלת. תכנן בהתאם.
אבטחה
אימות מתרחש בלחיצת היד (עוגיות עובדות) אבל הרשאה חייבת להתרחש על כל הודעה. לקוחות משקרים.
בדיקת קלט אינה בת-דיון. כל הודעה היא קלט לא אמין.
הגבלת קצב מונעת ספאם והתנהגות מרושעת.
מגבלות גודל הודעה מונעות מיצוי זיכרון.
WSS (WebSocket Secure) חובה בסביבת ייצור. אותו TLS שמגן על HTTPS.
אימות מקור במהלך לחיצת היד מונע חטיפת WebSocket חוצה-אתרים.
כשחיבורים נשברים
הם ישברו. רשתות נכשלות. שרתים מופעלים מחדש. מכשירים ניידים נרדמים.
פעימות לב מזהות חיבורים מתים. אין תגובת Pong? החיבור נעלם.
חיבור מחדש אוטומטי עם השהייה מעריכית. אל תפגיז שרת שנאבק.
מזהי הודעות או מספרי רצף מזהים פערים. שלח מחדש מה שאבד.
מנגנוני שחזור מאפשרים ללקוחות להשלים הודעות שהוחמצו לאחר ניתוקים קצרים.
מתי לא להשתמש ב-WebSockets
Server-Sent Events מטפלים בסטרימינג חד-כיווני מהשרת ללקוח בצורה פשוטה יותר. אם לקוחות רק מקבלים, שקול SSE.
HTTP רגיל עובד מצוין לתבניות בקשה-תגובה. אל תוסיף את המורכבות של WebSocket לפעולות שלא צריכות זמן אמת.
WebTransport (מבוסס HTTP/3) הוא העתיד ליישומים חדשים הזקוקים ליכולות דמויות-WebSocket עם ביצועים טובים יותר.
WebSockets זוהרים כשצריך שני הצדדים לדבר, כשזמן ההשהייה חשוב, כשזמן אמת אינו אופציונלי. הם הפרוטוקול שסוף סוף מאפשר לשרתים לפתוח שיחות.
שאלות נפוצות על WebSockets
האם WebSockets עובדים דרך חומות אש ו-proxies?
בדרך כלל כן. לחיצת היד נראית כמו HTTP, אז רוב התשתיות מאפשרות לה לעבור. WSS (פורט 443) עובד טוב יותר מ-WS (פורט 80) ברשתות מגבילות כיוון שנראה כמו תעבורת HTTPS רגילה.
כמה חיבורי WebSocket יכול שרת לטפל?
תלוי בשרת שלך ובמה שכל חיבור עושה. שרת מכוונן היטב יכול לטפל בעשרות אלפים עד מאות אלפים של חיבורים רדומים ברובם. חיבורים פעילים שמעבדים הודעות רבות יגיעו למגבלות מהר יותר. זיכרון ומתארי קבצים הם בדרך כלל האילוצים.
האם להשתמש ב-WebSockets או ב-socket.io?
socket.io מוסיף תכונות על גבי WebSockets: חיבור מחדש אוטומטי, ניהול חדרים, נסיגות לדפדפנים ישנים, ואישורי קבלה. אם אתה זקוק לתכונות האלה, socket.io חוסך עבודה. אם אתה רוצה עומס מינימלי ושליטה, WebSockets גולמיים פשוטים יותר.
האם WebSockets יכולים להחליף REST APIs?
הם יכולים, אבל בדרך כלל לא כדאי. חוסר-המצב של REST מקל עליו לשמור במטמון, להתרחב ולאבחן. השתמש ב-REST לפעולות CRUD טיפוסיות; השתמש ב-WebSockets לתכונות זמן אמת. יישומים רבים משתמשים בשניהם.
למה הודעות לקוח דורשות masking?
כדי למנוע התקפות הרעלת מטמון. ללא masking, לקוח זדוני יכול ליצור מסגרות WebSocket שנראות כמו תגובות HTTP תקינות ל-proxies מתווכים, ועלול להרעיל את המטמונים שלהם. המסיכה האקראית הופכת זאת לבלתי מעשי.
بۇ بەت پايدىلىق بولدىمۇ؟