עודכן לפני חודש
שרת בודד הוא מוגבל. הוא יכול לטפל רק במספר מסוים של חיבורים, לעבד רק מספר מסוים של בקשות, לשרת רק מספר מסוים של משתמשים. לחצו מעבר לגבול הזה והשרת מאט, מגמגם, נעצר. האפליקציה שלכם קורסת כי מכונה אחת לא הצליחה לעמוד בקצב.
מאזני עומס קיימים בגלל התמותה הזו. הם יושבים לפני מספר שרתים ומפיצים בקשות נכנסות ביניהם. שום שרת בודד אינו נושא את כל המשקל. וכאשר שרת אחד נכשל — כי שרתים תמיד נכשלים בסופו של דבר — האחרים ממשיכים לרוץ. המשתמשים לעולם אינם שמים לב.
שרת בודד יכול להיכשל. אלף שרתים מאחורי מאזן עומס? תמיד יש משהו שפועל.
הבעיה שמאזני עומס פותרים
כאשר האפליקציה שלכם גדלה מעבר לשרת אחד, יש לכם שתי אפשרויות.
הרחבה אנכית משמעה רכישת שרת גדול יותר. יותר CPU, יותר RAM, דיסקים מהירים יותר. זה עובד עד שזה לא עובד. גם השרת החזק ביותר שניתן לקנות בכסף עדיין מוגבל. ועדיין יש לכם שרת אחד — אם הוא נכשל, הכל נכשל.
הרחבה אופקית משמעה הוספת שרתים נוספים. אין תקרה. צריכים יותר קיבולת? הוסיפו שרת. אחד נכשל? האחרים ממשיכים. אבל הרחבה אופקית יוצרת בעיה חדשה: כיצד משתמשים יודעים לאיזה שרת להתחבר?
לא ניתן לצפות מהמשתמשים לבחור שרת. לא ניתן להקצות משתמשים לשרתים באופן ידני. אתם צריכים משהו שמציג כתובת אחת לעולם בעודו מפיץ את העבודה בסתר בין מכונות רבות.
המשהו הזה הוא מאזן עומס.
כיצד פועלים מאזני עומס
מבחוץ, משתמשים רואים כתובת אחת. הם מתחברים ל-loadbalancer.example.com ואין להם מושג שעשרה שרתים יושבים מאחוריה.
מאזן העומס מקבל כל חיבור נכנס ומקבל החלטה: איזה שרת אחורי צריך לטפל בבקשה הזו? הוא מעביר את הבקשה לשרת הנבחר, מקבל את התגובה, ושולח אותה בחזרה למשתמש.
אם שרת אחורי מת, מאזן העומס שם לב. הוא מפסיק לשלוח אליו תעבורה. הבקשות זורמות לשרתים הנותרים. המשתמשים לא חווים דבר — אולי כמה מילי-שניות של השהייה בזמן שבקשה שנכשלה מנסה מחדש על שרת תקין.
זה הערך המרכזי: הפשטה. המשתמשים רואים נקודת קצה אחת. ניתן להוסיף שרתים, להסיר שרתים, להחליף שרתים, והמשתמשים לעולם לא יודעים. מאזן העומס שומר על האשליה של אפליקציה בודדת ועמידה.
בחירת השרת שיקבל את הבקשה
האלגוריתם שבוחר איזה שרת מטפל בכל בקשה חשוב יותר ממה שאולי תחשבו.
Round-robin הוא הפשוט ביותר. הבקשה הראשונה הולכת לשרת A, השנייה לשרת B, השלישית לשרת C, ואז חזרה ל-A. כל שרת מקבל תעבורה שווה. זה עובד כאשר כל השרתים זהים וכל הבקשות דורשות בערך אותה כמות מאמץ.
אבל הבקשות אינן שוות. חלקן מכבידות על בסיס הנתונים. חלקן מחזירות נתונים ממטמון באופן מיידי. Round-robin מתעלם מזה. שרת שמעבד שאילתה כבדה מקבל את אותה תעבורה כמו שרת שמחזיר תגובות ממטמון. העומס הופך לאי-אחיד.
Weighted round-robin מתחשב בהבדלים בין שרתים. שרת עם משקל 3 מקבל פי שלושה בקשות מאשר שרת עם משקל 1. אם אתם מוסיפים מכונה חזקה יותר לקבוצה, תנו לה משקל גבוה יותר.
Least connections מנתב כל בקשה לשרת עם הכי מעט חיבורים פעילים כרגע. שרת שמעבד בקשות איטיות צובר חיבורים באופן טבעי. Least connections רואה זאת ושולח בקשות חדשות למקום אחר. העומס מאזן את עצמו.
Least response time הולך רחוק יותר: נתב לשרת עם הכי מעט חיבורים וזמני התגובה המהירים ביותר לאחרונה. שרת שגם פנוי וגם מהיר מקבל עדיפות.
IP hash משתמש בגיבוב של כתובת ה-IP של הלקוח כדי לבחור שרת. אותו לקוח תמיד מגיע לאותו שרת (אלא אם השרת נכשל). זה חשוב לשמירת קשר הסשן — אליה נחזור, כי זו מלכודת.
Least bandwidth מנתב לשרת שדוחף כרגע הכי פחות נתונים. שימושי עבור שרתי מדיה שבהם רוחב הפס, ולא ספירת הבקשות, הוא האילוץ.
רוב האפליקציות משתמשות ב-least connections או ב-round-robin. האלגוריתמים המתוחכמים חשובים בקנה מידה גדול, אבל הם לא יכולים להציל אתכם מבעיות ארכיטקטוניות יסודיות.
Layer 4 מול Layer 7
מאזני עומס יכולים לפעול ברמות שונות של מחסנית הרשת.
איזון עומס Layer 4 רואה רק כתובות IP ופורטים. הוא אינו מבין HTTP. הוא רק רואה "חיבור הגיע מ-IP זה לפורט זה" ומחליט לאן לשלוח אותו. מהיר. יעיל. פשטני.
איזון עומס Layer 7 מבין HTTP. הוא יכול לקרוא את ה-URL, לבדוק כותרות, לבחון עוגיות, ואפילו להסתכל על גוף הבקשה. זה מאפשר ניתוב מתוחכם: שלח בקשות /api/ לשרתי API, שלח /images/ לשרתי מדיה, נתב על בסיס כותרת ה-Authorization.
הפשרה היא מהירות. Layer 7 חייב לנתח HTTP, מה שדורש עיבוד רב יותר מאשר העברת החבילות הפשוטה של Layer 4. אבל מאזני עומס מודרניים של Layer 7 מטפלים במאות אלפי בקשות בשנייה. הגמישות שווה כמעט תמיד את המחיר.
רוב אפליקציות הרשת משתמשות ב-Layer 7. היכולת לנתב על בסיס תוכן, לסיים SSL באופן מרכזי, ולהוסיף ולשנות כותרות היא יקרת ערך מדי לוותר עליה לטובת רווחי מהירות שוליים.
בדיקות תקינות: לדעת מה פועל
מאזן עומס שמשלח בקשות לשרתים מתים גרוע מחסר תועלת. בדיקות תקינות מונעות זאת.
בדיקות תקינות אקטיביות: מאזן העומס מבצע בדיקה תקופתית לכל שרת אחורי. זה עשוי להיות ניסיון חיבור TCP, בקשת HTTP ל-/health, או בדיקה מתוחכמת יותר שמאמתת קישוריות לבסיס הנתונים. שרתים תקינים מגיבים. שרתים לא תקינים לא מגיבים. שרתים שנכשלו מוסרים מהקבוצה.
בדיקות תקינות פסיביות: מאזן העומס מנטר תעבורה אמיתית. אם שרת מתחיל להחזיר שגיאות 500 או פוקע זמנו על בקשות אמיתיות, הוא מסומן כלא תקין — אפילו אם בדיקות אקטיביות עוברות. לעתים שרתים חיים מבחינה טכנית אך שבורים מבחינה פונקציונלית.
כאשר שרת נכשל, התעבורה זורמת אוטומטית לשרתים תקינים. כאשר השרת המקולקל מתאושש ומתחיל לעבור בדיקות תקינות שוב, הוא מצטרף אוטומטית לקבוצה. אין צורך בהתערבות אנושית.
זו זמינות גבוהה. שרתים בודדים יכולים להיכשל. האפליקציה נשארת פעילה.
הצמדת סשן: רע הכרחי
חלק מהאפליקציות מאחסנות סשן משתמשים בזיכרון השרת. משתמש מתחבר בשרת A, הסשן שלו חי בשרת A. אם הבקשה הבאה שלו הולכת לשרת B, הוא נראה מנותק.
הצמדת סשן (או "sticky sessions") מבטיחה שהבקשות של המשתמש מגיעות בעקביות לאותו שרת. מאזן העומס עוקב אחר איזה שרת טיפל בבקשה הראשונה של המשתמש ומנתב אליו בקשות עוקבות.
ניתן לעשות זאת עם עוגיות (מאזן העומס מגדיר עוגייה המזהה את השרת האחורי) או IP hashing (אותו IP תמיד הולך לאותו שרת).
הנה הבעיה: הצמדת סשן מחלישה כל מה שמאזני עומס מספקים לכם. רציתם פיזור ויתירות. עכשיו אתם מנתבים משתמשים לשרתים ספציפיים. אם השרת הזה מת, המשתמשים מאבדים את הסשן שלהם. יצרתם מחדש את נקודת הכשל הבודדת שניסיתם להימנע ממנה.
הפתרון האמיתי: אל תאחסנו סשנים על שרתים. אחסנו אותם ב-Redis, בבסיס נתונים, או במיקום משותף אחר. כל שרת יכול לטפל בכל בקשה. שרת מת? המשתמשים ממשיכים בצורה חלקה בשרת אחר, כשהסשנים שלהם שמורים. Sticky sessions הופכות מיותרות.
הצמדת סשן היא קביים לארכיטקטורות שלא תוכננו לפיזור. אם אתם מתחילים מחדש, תכננו למצב משותף מההתחלה.
איזון עומס גלובלי: מספר מרכזי נתונים
עבור אפליקציות גלובליות באמת, איזון העומס מתרחש ברמת ה-DNS לפני שחיבורי TCP אפילו מתחילים.
משתמש בטוקיו שואל DNS לגבי האפליקציה שלכם. DNS מחזיר את כתובת ה-IP של מרכז הנתונים שלכם בטוקיו. משתמש בלונדון מקבל את כתובת ה-IP של מרכז הנתונים שלכם בלונדון. משתמשים מתחברים אוטומטית לשרתים קרובים, מה שמקטין את ההשהייה.
אם מרכז הנתונים שלכם בטוקיו נכשל, DNS מפסיק להחזיר את כתובת ה-IP שלו. משתמשי טוקיו מנותבים למרכז הנתונים הקרוב ביותר הבא. מעבר חירום ברמה הגיאוגרפית.
הבעיה: מטמון DNS. כאשר אתם מעדכנים DNS, התשובות הישנות נשארות במטמונים ברחבי העולם לדקות עד שעות. מעבר חירום מבוסס DNS אינו מיידי. רוב האפליקציות הגלובליות משלבות ניתוב גיאוגרפי ברמת ה-DNS עם איזון עומס ברמת האפליקציה בתוך כל אזור.
זמינות מאזן העומס
מאזני עומס פותרים נקודות כשל בודדות עבור שרתי האפליקציה שלכם. אבל מאזן העומס עצמו יכול להיכשל. אם כן, כל השרתים האחוריים התקינים האלה הופכים ללא נגישים.
Active-passive: שני מאזני עומס. אחד מטפל בתעבורה. השני צופה ומחליף אם הראשי נכשל. יתירות פשוטה, אבל מחצית מקיבולת איזון העומס שלכם יושבת בטלה.
Active-active: מספר מאזני עומס מטפלים בתעבורה בו-זמנית. DNS מפיץ לקוחות ביניהם, או ניתוב ברמת הרשת (ECMP) מפזר חיבורים. יותר מורכב, אבל אין בזבוז קיבולת.
Cloud load balancers: AWS, Google Cloud ו-Azure מספקים איזון עומס כשירות מפוזר. הם כבר יתירים על פני אזורי זמינות. אתם לא מגדירים מעבר חירום — הוא מובנה.
רוב הפריסות המודרניות משתמשות ב-cloud load balancers ואינן חושבות כלל על זמינות מאזן העומס. ספק הענן מטפל בכך.
חומרה, תוכנה, או ענן?
מאזני עומס חומרה הם מכשירים ייעודיים. F5, Citrix. ביצועים גבוהים, תכונות מיוחדות, יקרים. הרחבה פירושה רכישת חומרה נוספת. נמצאים בעיקר בארגונים עם תשתית ישנה.
מאזני עומס תוכנה פועלים על שרתים רגילים. Nginx, HAProxy, Envoy, Traefik. גמישים, חסכוניים, ניתנים להרחבה על ידי הוספת מופעים. אתם מנהלים אותם בעצמכם.
Cloud load balancers הם שירותים מנוהלים. AWS ALB/NLB, Google Cloud Load Balancing, Azure Load Balancer. אין תשתית לנהל, הרחבה אוטומטית, תשלום לפי שימוש. יקרים יותר לכל בקשה מאשר ניהול עצמי, אבל ללא נטל תפעולי.
התעשייה עברה לכיוון תוכנה וענן. מאזני עומס חומרה הולכים ונדירים מחוץ לסביבות ישנות.
אבטחה בקצה הרשת
מאזני עומס יושבים בקצה הרשת שלכם, מה שהופך אותם למקומות טבעיים ליישום אבטחה.
SSL/TLS termination: מאזני עומס מטפלים ב-HTTPS, מפענחים תעבורה לפני העברתה לשרתים האחוריים. השרתים האחוריים מקבלים HTTP רגיל ברשת הפנימית. ניהול אישורים מתרחש במקום אחד במקום על כל שרת.
ספיגת DDoS: מאזני עומס יכולים לספוג קפיצות תעבורה, להגביל קצב לקוחות בודדים, ולסנן בקשות זדוניות ברורות. הם קו ההגנה הראשון.
חומות אש לאפליקציות רשת: חלק ממאזני העומס כוללים פונקציונליות WAF — חסימת SQL injection, XSS ומתקפות ברמת האפליקציה לפני שהן מגיעות לשרתים שלכם.
בקרת גישה: רשימות היתר וחסימה של כתובות IP במאזן העומס חוסמות תעבורה לפני שהיא נוגעת באפליקציה שלכם.
הצבת אבטחה במאזן העומס מאפשרת לשרתים האחוריים להתמקד בלוגיקת האפליקציה. הם בוטחים שתעבורה שמגיעה אליהם כבר עברה אימות.
שאלות נפוצות על מאזני עומס
מה קורה לבקשות שבאמצע הדרך כאשר שרת נכשל?
הבקשות הספציפיות האלה נכשלות — אין שחזור קסם. אבל מאזן העומס מזהה מיד את הכשל דרך בדיקות תקינות ומפסיק לנתב אליו בקשות חדשות. רוב הלקוחות מנסים מחדש בקשות שנכשלו באופן אוטומטי. משתמשים עשויים לחוות עיכוב קצר, אבל בקשות עוקבות מצליחות על שרתים תקינים.
כיצד מאזני עומס מטפלים בחיבורי WebSocket?
WebSockets הם חיבורים ארוכי חיים. מאזני עומס שומרים על מיפוי החיבורים — ברגע שחיבור WebSocket מתחבר לשרת אחורי, החיבור נשאר שם לכל משך חייו. מאזני עומס של Layer 7 יכולים לבחון את בקשת ה-HTTP upgrade הראשונית לצורך החלטות ניתוב, אבל ברגע שהשדרוג התרחש, החיבור נמשך.
האם ניתן להריץ מאזן עומס על אותו שרת כמו האפליקציה שלי?
מבחינה טכנית כן, אבל זה מסכל את המטרה. מאזן העומס צריך להיות נפרד כדי שישרוד כאשר שרתי אפליקציה נכשלים. הפעלת שניהם יחד יוצרת את נקודת הכשל הבודדת שאתם מנסים לחסל.
כמה שרתים אחוריים אני צריך?
לפחות שניים — אחרת אין לכם יתירות. מעבר לכך, תלוי בתעבורה שלכם ובכמה קיבולת שמורה אתם רוצים לכשל שרתים. אם יש לכם שלושה שרתים ואחד נכשל, אבדתם 33% מהקיבולת. עם עשרה שרתים, אבדתם 10%.
מתי כדאי להשתמש במספר מאזני עומס?
כאשר מאזן העומס עצמו הופך לצוואר בקבוק (נדיר עם חומרה/ענן מודרני) או כאשר אתם צריכים יתירות למאזן העומס עצמו. תצורות active-active עם ניתוב DNS או ECMP מספקות גם קיבולת מוגברת וגם מעבר חירום.
האם דף זה היה מועיל?