1. ספרייה
  2. HTTP והרשת
  3. פרוטוקולי ווב מודרניים

עודכן לפני חודש

HTTP/1.1 אילץ את הדפדפן שלך להעמיד פנים שהוא שישה לקוחות שונים, לפתוח שישה חיבורים נפרדים לאותו שרת, רק כדי לטעון דף במהירות סבירה. ריבוי הערוצים של HTTP/2 סוף סוף אפשר לדפדפנים להיות כנים לגבי מה שהם עושים: חיבור אחד, בקשות רבות במקביל, ללא המתנה בתור.

האבסורד ש-HTTP/2 בא לתקן

HTTP/1.1 מעבד בקשות ברצף. כאשר הדפדפן שלך מבקש משאב, עליו להמתין לתגובה המלאה לפני שליחת הבקשה הבאה על אותו חיבור. זוהי חסימת ראש-התור — תגובה איטית עוצרת את כל מה שמחכה מאחוריה.

דפדפנים עקפו זאת על ידי פתיחת מספר חיבורים לכל דומיין, בדרך כלל שישה. זה יצר מקביליות בכוח גס, אך עם עלויות כבדות. כל חיבור TCP דורש לחיצת יד משלו, מה שמבזבז זמן ומשאבים. כל אחד שומר על בקרת עומסים נפרדת, המונעת שימוש אופטימלי ברוחב הפס. כל אחד מתחיל לאט בשל ההתנעה האיטית של TCP, ומאיץ בהדרגה במקום לשדר במהירות מלאה.

דפי אינטרנט עם עשרות או מאות משאבים סבלו. אפילו עם שישה חיבורים, משאבים נערמו בתור וחיכו לפתח. מפתחים פנו לפריצות יצירתיות יותר ויותר:

פיצול דומיינים פרס משאבים על פני מספר דומיינים מזויפים — images.example.com, scripts.example.com, styles.example.com — רק כדי לרמות דפדפנים לפתוח חיבורים נוספים. הפרוטוקול היה שבור כל כך שלשקר לו היה שיטת עבודה מקובלת.

שרשור משאבים צרף קבצים קטנים רבים לקבצים גדולים, מה שהפחית את מספר הבקשות על חשבון יעילות המטמון וגמישות. צריך לתקן שורת CSS אחת? כל החבילה מתבטלת.

אלה לא היו פתרונות אלגנטיים. האינטרנט נלחם בפרוטוקול שלו עצמו.

כיצד ריבוי הערוצים עובד בפועל

HTTP/2 מתייחס לחיבור לא כצינור הנושא דבר אחד בכל פעם, אלא כערוץ הנושא דברים רבים בו-זמנית.

האבסטרקציה המרכזית היא הזרם. כל זוג בקשה-תגובה מקבל זרם, המזוהה במספר. זרמים מרובים חולקים חיבור אחד. התקשורת מתבצעת דרך מסגרות — נתחים קטנים של נתונים המתויגים עם מזהה הזרם שלהם.

כאשר הדפדפן שלך צריך עשרה משאבים, הוא שולח את כל עשר הבקשות מיד. השרת מעבד אותן במקביל ושולח מסגרות תגובה כשהן מוכנות. המסגרות משתלבות זו בזו — נתח מזרם 1, אחר כך זרם 3, אחר כך עוד מזרם 1, אחר כך זרם 7. הדפדפן מרכיב מחדש כל זרם מהמסגרות שלו.

מנקודת המבט של היישום, זה עדיין נראה כמו זוגות בקשה-תגובה מסורתיים. אך מתחת לפני השטח, הכל זורם דרך חיבור מרובה-ערוצים אחד.

מה זה בעצם נותן לך

לא יותר המתנה בתור. משאבים לא נערמים מאחורי זה. כל הבקשות יוצאות מיד; תגובות מגיעות מהר ככל שהשרת יכול לייצר אותן.

חיבור אחד עושה את עבודת השישה. פחות לחיצות יד, פחות זיכרון, עומס מעבד נמוך יותר בשני הקצוות. השרת לא מגלגל מאות חיבורים מאותו דפדפן.

שימוש טוב יותר ברוחב הפס. כל הזרמים חולקים חלון עומסים TCP אחד. במקום שישה חיבורים שכל אחד מאיץ מהתנעה איטית, חיבור אחד שומר על תפוקה אופטימלית.

הפריצות הופכות למיותרות. פיצול דומיינים פוגע ב-HTTP/2 — הוא מונע שימוש חוזר בחיבור. לשרשור אין יתרון עוד, אך עלויותיו נשארות. קבצים קטנים רבים עובדים מצוין עכשיו.

תעדוף הופך לאפשרי. דפדפנים יכולים לספר לשרתים אילו משאבים הכי חשובים. HTML ו-CSS לפני סקריפטים אנליטיים. תוכן קריטי לפני תוכן שאפשר גם בלעדיו.

שכבה בינארית מתחת לכל

HTTP/1.1 היה מבוסס-טקסט. יכולת לקרוא אותו בעיניים:

GET /index.html HTTP/1.1
Host: example.com

HTTP/2 הוא בינארי. כל הודעה היא מסגרת עם מבנה מדויק: כותרת של 9 בייטים המציינת אורך, סוג, דגלים ומזהה זרם, ואחריה מטען.

סוגי מסגרות נפוצים:

  • DATA: נושא גוף בקשה או תגובה
  • HEADERS: נושא כותרות HTTP (דחוסות)
  • SETTINGS: מעביר הגדרות תצורה
  • RST_STREAM: מסיים זרם באמצע הדרך
  • PING: מודד זמן הלוך-חזור (RTT)

פרוטוקולים בינאריים מנותחים מהר יותר ומעורפלים פחות מפרוטוקולי טקסט. הפשרה היא שאי אפשר לאבחן תקלות על ידי מבט בבייטים גולמיים. אבל כלי הפיתוח של הדפדפן ו-Wireshark מטפלים ב-HTTP/2 בלי בעיה — בפועל זה כמעט אף פעם לא בעיה.

בקרת זרימה מונעת כאוס

ריבוי זרמים על חיבור אחד יוצר בעיה חדשה: מה מונע מזרם מהיר להרעיב את כל השאר?

HTTP/2 מיישם בקרת זרימה בשתי רמות. בקרת זרימה ברמת החיבור שולטת על התפוקה הכוללת. בקרת זרימה ברמת הזרם מנהלת כל זרם באופן עצמאי.

מקבלים מפרסמים גדלי חלון — כמה נתונים הם מוכנים לקבל. שולחים חייבים להישאר בתוך החלונות הללו. כאשר מקבלים מעבדים נתונים, הם שולחים עדכוני חלון המאפשרים לזרום עוד.

זה מונע משרת מהיר להציף לקוח איטי, מבטיח שיתוף הוגן בין זרמים, ומאפשר למקבלים לקבוע אילו זרמים יקבלו עדיפות.

תעדוף זרמים (בתיאוריה)

HTTP/2 מאפשר ללקוחות להקצות עדיפויות לזרמים. זרמים יכולים להיות תלויים בזרמים אחרים — CSS תלוי ב-HTML, מה שמעיד שעליו להמתין. לזרמים יכולים להיות משקלים המעידים על חשיבות יחסית.

בפועל, הדבר זכה לשימוש מועט. דפדפנים יישמו זאת בדרכים שונות. שרתים רבים התעלמו לחלוטין מעדיפויות. המנגנונים היו מורכבים לשימוש נכון. HTTP/3 החליף זאת בתוכנית עדיפויות פשוטה יותר.

דחיפת שרת (הדרך שלא נבחרה)

HTTP/2 הציג את מושג דחיפת השרת: שרתים יכולים לשלוח משאבים לפני שדפדפנים ביקשו אותם. בעת שליחת HTML, השרת עשוי לדחוף את ה-CSS וה-JavaScript שהוא יודע שהדפדפן יצטרך להם, ובכך לחסוך הלוך-חזור שלם.

הדבר זכה לאימוץ מוגבל. הבעיה המרכזית: שרתים לא יודעים מה כבר שמור במטמון של הדפדפן. דחיפת משאבים ממוחסנים מבזבזת רוחב פס. פתרונות שהוצעו, כמו cache digests, מעולם לא קנו אחיזה. רוב האתרים משתמשים כיום ברמזי preload במקום — מיידעים את הדפדפן על משאבים חשובים מבלי לדחוף אותם.

מיזוג חיבורים

HTTP/2 יכול לעשות שימוש חוזר בחיבור אחד עבור מספר דומיינים, כל עוד הם מפנים לאותה כתובת IP ומציגים אישור תקף המכסה את כל הדומיינים.

אם example.com ו-cdn.example.com שניהם מפנים לאותו שרת עם אישור wildcard, הדפדפן שלך עשוי להשתמש בחיבור אחד לשניהם — מה שמפחית את התקורה עוד יותר.

הדבר דורש תצורת אישור קפדנית וכתובות IP זהות. דפדפנים מסוימים שמרנים לגבי מתי הם מבצעים מיזוג.

המגבלה ש-HTTP/3 פותר

HTTP/2 ביטל את חסימת ראש-התור ברמת HTTP. אך חסימה ברמת TCP נותרת.

TCP מבטיח מסירה מסודרת. אם מנה אבדה, TCP ממתין להעברה חוזרת שלה לפני מסירת המנות הבאות — גם אם אותן מנות שייכות לזרמי HTTP/2 שונים שלא אכפת להם אחד מהשני.

מנה אחת שאבדה עוצרת את כל הזרמים. ריבוי הערוצים שביטל צורה אחת של חסימת ראש-התור נתקל באחרת — הפעם בשכבת התעבורה.

HTTP/3 מטפל בזה על ידי החלפת TCP ב-QUIC, שמטפל בזרמים באופן עצמאי ברמת התעבורה. מנה שאבדה משפיעה רק על הזרם שלה.

מעבר מ-HTTP/1.1

בטל את הפריצות. פיצול דומיינים פוגע ב-HTTP/2 על ידי מניעת שימוש חוזר בחיבור. שרשור משאבים מונע מטמון גרגירי. קבצים קטנים רבים עובדים מצוין עכשיו.

ודא שהתשתית שלך מוכנה. חלק מהפרוקסיים, חומות האש ורשתות ארגוניות מפריעות ל-HTTP/2. הבטח מעבר חלק ל-HTTP/1.1 במקרה הצורך.

מדוד את התוצאות. לא כל האתרים נהנים באותה מידה. חיבורים עם זמן השהייה גבוה רואים את הרווחים הגדולים ביותר — הפחתה של 30-50% בזמן ההשהייה היא נפוצה. חיבורים מקומיים עם זמן השהייה נמוך רואים שיפור מתון יותר.

HTTP/2 דורש HTTPS

HTTP/2 תוכנן להפעלה הן מעל HTTP והן מעל HTTPS, אך דפדפנים מיישמים אותו רק מעל HTTPS. זה היה מכוון — המהלך דחף קדימה את אימוץ HTTPS.

במהלך לחיצת היד של TLS, הלקוח והשרת משתמשים ב-ALPN (Application-Layer Protocol Negotiation) כדי להסכים על HTTP/2 אם שניהם תומכים בו.

שאלות נפוצות על ריבוי ערוצים ב-HTTP/2

מדוע דפדפנים הגבילו את עצמם לשישה חיבורים לכל דומיין?

מפרט HTTP/1.1 המליץ ללקוחות לא לפתוח יותר משני חיבורים לכל שרת, כדי לא לנצל משאבים שלא לצורך. דפדפנים התיישבו בסופו של דבר על שישה כפשרה מעשית בין מקביליות לעומס שרת. HTTP/2 הופך את זה לבלתי רלוונטי — חיבור אחד מטפל בהכל.

האם HTTP/2 מאיץ את האתר שלי אוטומטית?

בדרך כלל כן, אבל לא תמיד. אתרים עם משאבים קטנים רבים רואים את הרווחים הגדולים ביותר. אם האתר שלך כבר משתמש במשאבים מעטים או בטכניקות אופטימיזציה של HTTP/1.1, השיפורים עשויים להיות צנועים. אתרים שעדיין משתמשים בפיצול דומיינים עשויים דווקא להאט — עד שיסירו אותו.

האם אני יכול להשתמש ב-HTTP/2 ללא HTTPS?

מבחינה טכנית כן — הפרוטוקול תומך בזה. מבחינה מעשית לא — דפדפנים מיישמים HTTP/2 רק מעל HTTPS. תזדקק לאישור TLS.

מדוע דחיפת שרת לא זכתה לאימוץ?

הבעיה הבסיסית: שרתים לא יכולים לדעת מה כבר שמור במטמון של הדפדפן. דחיפת משאבים שכבר ממוחסנים מבזבזת רוחב פס ועלולה דווקא להאט דברים. ללא דרך אמינה לדעת מה לדחוף, רוב המימושים דחפו יותר מדי — או ויתרו לחלוטין.

האם HTTP/2 מוחלף על ידי HTTP/3?

HTTP/3 מטפל במגבלת חסימת ראש-התור TCP של HTTP/2 על ידי שימוש ב-QUIC במקום TCP. אך HTTP/2 נותר בשימוש נרחב ויתקיים לצד HTTP/3 עוד שנים רבות. רוב מה שתלמד על ריבוי ערוצים ב-HTTP/2 חל גם על HTTP/3.

האם דף זה היה מועיל?

😔
🤨
😃