Nginx כ-Reverse caching proxy

אני מתקין בימים אלה עבור לקוח ביוון שרת Reverse caching proxy,

הלקוח מפעיל אתר חדשות על בסיס WordPress עם mysql, php-cgi ו-Apache, ויש המון קפיצות תעבורה פתאומיות (מ-350 בקשות בשנייה ל-1800), בנוסף יש לגולשים אפליקציה שמקבלת את הנתונים מהאתר באמצעות XML.

השרת של הלקוח נחנק מספר פעמים ביום עקב העומס, הצעתי לו שאני אתקין את Nginx לפני Apache וש-Nginx ישמור דפים דינאמים ו-XML במשך 3 דקות למשתמשים בלי עוגייה ובנוסף יגיש את התוכן הסטטי ישירות מה-HD.

התוצאה: כרגע (שעת הלחץ של האתר) יש 2500 איש באתר שמחוברים מ-PC, ועוד 10,000 בקשות בדקה ל-XML שונים, ה-Load avarage עומד על 0.55, ו-Apache מקבל בסה"כ 100 בקשות בדקה (לפני ההתקנה המספר הזה עמד על 5 ספרות).

חג שמח,

אבי.

פורסם בקטגוריה כללי | להגיב

כמה מילים על proxy_cache_lock ב-Nginx

תחשבו על התרחיש הבא:

יש לכם אתר עם עשרות אלפי מבקרים בדקה, אתם מפעילים שרת Reverse Proxy עם Cache ויש לכם בממוצע 50 אלף איש באתר בדקה, נניח שתוקף העמוד הראשי פג (Cache-Control) ויש 5000 בקשות לדף הבית באותו רגע, ללא קינפוג נכון של שרת ה-Reverse Proxy, כדי לרענן את דף הבית השרת יעביר את כל הבקשות לשרתי ה-Backend, שרתי ה-Backend לא יכולים לעמוד בעומס כזה ולכן ייתקעו, כמה שניות לאחר מכן שרת ה-Reverse Proxy יעביר עוד אלפי בקשות ל-Backend התקוע ויתחיל להחזיר אלפי הודעות שגיאה עם Proxy read timeout למאות הבקשות הראשונות והמרחק מכאן לקדחת לא רחוק בכלל.

בדיוק בשביל זה יש את  proxy_cache_lock, במקרה שיש מספר בקשות קובץ/דף ספציפי באותו הזמן, Nginx יחזיק את כל הבקשות בהמתנה ויעביר בקשה אחת בלבד אחורה ל-Backend, כאשר הפלט של הבקשה יתקבל, Nginx ישמור את הבקשה ב-Cache ויעביר את הפלט לכל אותם אלפי הבקשות שבהמתנה.

אגב את אותו הפתרון, ניתן ליישם גם ב-Varnish.

פורסם בקטגוריה כללי | להגיב

האצת ביצועי Reverse proxy ע"י SSH Tunnel

לפני מספר ימים כתבתי על האצת אפליקציה על גבי שימוש ב-Reverse Proxy, הפתרון יעיל כמו CDN (ועולה רבע מהעלות של CDN) ומאפשר לשמור על גמישות מבחינת הפעלת המערכת (לדוגמא – הטמעת Memcached בעתיד),

בפרויקט אני משתמש ב-Nginx (הלחם מילים של Engine-X), אבל ל-Nginx יש חיסרון אחד כ-Reverse Proxy, הוא לא תומך ב-KeepAlive, ולכן כל פניה לשרת המקור, דורש פתיחת חיבור TCP חדש וככל שהמרחק הפיזי בין שרת ה-Reverse Proxy לשרת המקור גדל כך זמן פתיחת חיבור ה-TCP.

כדי לתאר איך עובד KeepAlive – תחשבו על צינור מים של 10 מטר:

  • ללא KeepAlive – הצינור מתרוקן בין פעילות לפעילות ועוברות מספר שניות מרגע פתיחת הזרם (פתיחת החיבור) עד ליציאת המים בקצה הצינור (תחילת הגעת המידע – TTFB).
  • עם KeepAlive – בין פעילות לפעילות עוברים בצינור כמות מזערית של מים, כדי שבעת פתיחת הברז מיד יצאו המים.
כדי לייעל את ה-Reverse Proxy, הקמתי SSH Tunnel בין ה-Reverse Proxy לשרת המקור, SSH Tunnel יוצר חיבור (מוצפן) בין שני השרתים והחיבור הזה מתפקד (במקרה הזה) כתחליף ל-KeepAlive, כאשר ה-Reverse Proxy משתמש בחיבור הקיים של ה-SSH Tunnel ומעביר דרכו את הבקשות לשרת המקור.
כדי להציג את ההבדלים בין SSH Tunnel לחיבור ישיר, הקמתי שרת Reverse Proxy ע"ג Nginx בשרת בקנדה ופתחתי SSH Tunnel בין השרת בקנדה לשרת נוסף בישראל כאשר ה-Caching מבוטל (כל בקשה מועברת לשרת המקור בישראל):  
הערה: מדובר ב-2 בקשות זהות, לקובץ במשקל של 5Kb, בקשה אחת ב-HTTP והנוספת ב-HTTPS SSL
באמצעות חיבור ישיר:

  • הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTP רגילה: 660MS.
  • הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTPS מוצפנת: 760MS.
Reverse Proxy Over SSH Tunnel:

  • הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTP רגילה: 310MS.
  • הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTPS מוצפנת: 400MS.

שימו לב להבדל, בזמני ה-TTFB:

  • ב-HTTP, שימוש ב-SSH Tunnel השיג שיפור של 350MS, שיפור של 53%!
  • ב-HTTPS, שימוש ב-SSH Tunnel השיג שיפור של 360MS, שיפור של 52%!

לסיכום, ניתוב בקשות שרת Reverse Proxy דרך SSH Tunnel משפר ביצועים פי 2, עכשיו נותר רק לבדוק את אחוז השיפור עם 100 בקשות בשנייה (SSH Tunnel מצפין את התוכן ולכן יש זמן מעבד המושקע בהצפנה).
חג שמח ושנה טובה לכל בית ישראל,
אבי.
פורסם בקטגוריה כללי | להגיב

האצת אפליקצית סלולר באמצעות Reverse proxy

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

בגלל שמדובר רשת סלולרית, ה-Latency גבוה ולכן יש חשיבות גדולה מאוד ל-API מהיר במיוחד. בנוסף, ה-API חייב להכיל Secure Token כדי להגן על מסד הנתונים מפני שימוש בלתי מורשה/הצפה של המערכת וכדי להגן על משתמש האפליקציה (מהסביבה שלו) בעת שימוש ב-WIFI כל המידע יעבור דרך SSL.

"אז מה הבעיה? תשתמש ב-CDN"

יש כמה סיבות למה לא כדאי להשתמש ב-CDN:

  • השימוש ב-SSL יצרוך תעבורה נוספת והעלות תהיה גבוהה עוד יותר.
  • מדובר בפרויקט לטווח ארוך ובמידה והאפליקציה תצליח, העלויות הגבוהות של שימוש ב-CDN יגמרו את כל התקציב לפני שהפרויקט יגיע לאיזון כלכלי.
  • כמעט שום חברת CDN לא מאפשרת שימוש ב-Secure token, בודדות החברות שכן (הן דורשות SSL ועוד 200$~ כל חודש בשביל האפשרות הזאת) ואני לא מעוניין בחתונה קתולית עם שום חברה.
  • כבר היום יש לי שרתים בארה"ב ובאירופה שניתן להשתמש בהם.
  • בעתיד אני יכול להשיג ביצועים טובים יותר באמצעות הטמעת Memcached במערך (שכפול המסד ל-Memcached ופיזור הנתונים ב-3 שרתי Memcached – שרת בכל יבשת).

הפתרון: שימוש בשרתי GeoIP Reverse proxy עם Secure Tokens:

שרת ה-WEB הראשי ומסדי הנתונים יישבו בישראל, (כדי להפעיל את השירות בצורה מיטבית אני צריך שרתי Daemon הפזורים ב-3 יבשות (בנקודות הביקוש הגדולות ביותר), השרתים צריכים לתמוך ב:

  • HTTPS (תמיכה ב-SSL).
  • Reverse Proxy & Cache.
  • שרת קליל שיכול לעמוד בעומס של המון בקשות.
  • Secure tokens.
  • שינוי קונפיגורציה ללא Restart.
לסיכום:

ה-Reverse proxy היעיל ביותר שתומך בכל הפונקציות האלו הוא Nginx ולכן גם אשתמש בו לפרויקט, לצערי הוא לא השרת המהיר ביותר, Varnish יכול לטפל בעשרות אלפי בקשות בשנייה, אבל Varnish לא תומך ב-Secure tokens וב-SSL).

פורסם בקטגוריה כללי | תגובה אחת

השפעת מספר הגולשים על זמן התגובה של השרת

אני עובד בימים אלה על אפיון אפליקציה חדשה לסמארטפון, האפליקציה יוצרת קשר עם השרת מעת לעת ונושא הביצועים חשוב מאוד, כמו כן, כדי להגן על המשתמש (מהסביבה שלו), כאשר המשתמש מחובר באמצעות WIFI החיבור מתבצע באמצעות SSL.

בגלל שנושא הביצועים מאוד חשוב באפליקציה מהסוג הזה, אני מבצע מספר בדיקות ביצועים בצד ה-Backend לבדיקת תפקוד השרת בזמנים עמוסים כחלק מכתיבת האפיון. צד השרת רץ על VPS בארה"ב, באמצעות Nginx עם Secure links (שימוש באסימון – Token) כאשר כל הנתונים נמשכים באמצעות Reverse proxy משרת Apache בישראל ונשמרים ב-Cache ל-8 שעות.

הנתונים שמוצגים בגרף הם טעינה של 18 אלמנטים, כולם ב-Cache, ב-3 מצבים שונים (מימין לשמאל):

  • כאשר יש פנייה מגולש אחד מהאפליקציה לשרת.
  • כאשר יש פנייה מ-100 גולשים באפליקציה לשרת.
  • כאשר יש פנייה מ-250 גולשים באפליקציה לשרת.

מפל המים מורכב ממספר אלמנטים:

  • האלמנט הראשון הוא קובץ טקסט שמכיל 17 קישורים שונים לאותו הקובץ, קריאה אחת ב-HTTP, קריאה שאחריה ב-HTTPS וחוזר חלילה.
  • אלמנטים 2-17 הם אותו הקובץ שנטען כל פעם מחדש.
  • אלמנט 18 הוא קובץ favicon.ico.

שימו לב למסקנות המפתיעות:

  • בקפיצה ממשתמש 1 ל-100, זמן הקריאה ב-HTTP גדל ב-100MS בממוצע, זמן הקריאה ב-HTTPS גדל פי 2 בממוצע.
  • בקפיצה מ-100 משתמשים ל-250 משתמשים, זמן הקריאה ב-HTTP גדל ב-30MS בממוצע, זמן הקריאה ב-HTTPS גדל ב-30MS בממוצע. – גידול של פי 1.5 בכמות הבקשות, אך זמן הקריאה גדל ב-30MS בממוצע.
  • בקפיצה ממשתמש 1 ל-250, זמן הקריאה ב-HTTP גדל פי 1.2 בממוצע, זמן הקריאה ב-HTTPS גדל פי 2.1 בממוצע.
  • Nginx בקושי העמיס על ה-VPS, לא ניצל את כל המעבד, וזה דיי מפתיע, עדיף NGINX מעמיס ומהיר מאשר NGINX קליל ואיטי.

הערה: בדיקות מפלי המים בוצעו באמצעות Webpagetest.org, בדיקות העומס בוצעו באמצעות Blitz.io.

אבי ק.

פורסם בקטגוריה לינוקס | להגיב

אינטרנט רימון מנותקים מהאינטרנט

זוכרים את ערים מנותקות מהאינטרנט?

בעקבות תקלה טכנית, לקוחות האינטרנט של אינטרנט רימון לא יכולים לגלוש במשך יותר משעה (בפעם המי יודע כמה),

הנה הגרף:

 

שימו לב שאינטרנט רימון בבעלות חלקית של נטוויזן (שנקנתה על ידי סלקום). מוזר מאוד שנטוויזן מסכימה לרמת שירות שכזו.

פורסם בקטגוריה כללי | להגיב

יצאת צדיק 27/08/2012 21:00

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

פורסם בקטגוריה כללי | להגיב

טיפול יעיל ב-Backend איטי

בפוסט הבא אני רוצה להציג פתרון לבעיה שקיימת בהרבה אתרים, כשה-Time to first byte (הזמן העובר מתחילת החיבור לשרת עד שהביט הראשון נשלח מהשרת לדפדפן) גבוהה מדי.

היחס הממוצע בזמן המושקע בגלישה בעמוד בין ה-Backend (השרת מייצר את התוכן) ל-Frontend (הדפדפן מוריד את התוכן ופורס את העמוד) עומד על 20%/80%. כלומר, אם דף הבית (הדף עצמו, ללא תמונות/JS וכו') נטען תוך 2 שניות, 400 מילישנייה מוקדשים ליצירת העמוד.

הזמן האופטימלי ל-TTFB הוא 200 מילישנייה, אבל, כאשר באתר שלך יש:

  • שאילתות SQL מורכבות.
  • שאילתות SQL שלא כתובות כהלכה – לדוגמא: Order by rand().
  • שימוש ב-API בתוך הקוד (ה-TTFB של ה-API מאט את יצירת העמוד).
  • קוד בעייתי (sleep?).

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

כדי לייעל את טעינת העמוד, אנו מעוניינים לשלוח לדפדפן את ה-Header בזמן שהשרת ממשיך ביצירת ה-Body וה-Footer , בזמן הזה, הדפדפן כבר יוריד/יטען מה-Cache את קבצי ה-CSS, JS, תוספים חברתיים וכו' המופיעים ב-Header וטעינת האתר ופריסתו תהיה מהירה יותר.

כדי לשלוח את ה-Header, נשתמש בפונקציה Flush, ונמקמה בתחתית ה-Header – כדי לשלוח כמה שיותר תוכן לדפדפן.

 איך זה נראה בפועל?

כדי להציג את ההבדלים בין שימוש ב-Flush לבין עבודה ללא Flush, אציג את השינוי באתר Fmylife.co.il (אתר Development לפרויקט עתידי).

כמה מילים על Fmylife: הסקריפט בנוי ב-PHP, הטמפלייט ב-Smarty, ביצעתי מס' תיקונים ושינויים בסקריפט, בנוסף, מאחר ומדובר בסקריפט "חברתי" (במערכת יש שימוש ב-Google plus, FB Like ו-Twitter), האתר נטען תוך 6 שניות בממוצע (תלוי במצבי רוח של טוויטר).

זמן טעינת עמוד הבית ללא פונקציית Flush:

מקרא:

  • כתום – יצירת חיבור.
  • ירוק – TTFB.
  • כחול – זמן הורדה.
  • קו ירוק (בצמוד ל-1.2) – תחילת פריסת העמוד בדפדפן)

מבחינת ביצועים המצב לא מושלם, זמן ה-TTFB עומד על 500 מילישנייה ותחילת טעינת CSS הוא לאחר 700 מילישנייה מטעינת דף הבית, הדפדפן מתחיל לפרוס את העמוד לאחר 1.1 שנייה מתחילת הטעינה (מומלץ לסיים את טעינת הדף תוך 2 שניות). בשורה התחתונה – יש מה לשפר.

זמן טעינת עמוד הבית עם פונקציית Flush:

מקרא:

  • כתום – יצירת חיבור.
  • ירוק – TTFB.
  • כחול – זמן הורדה.
  • קו ירוק (בצמוד ל-1.0) – תחילת פריסת העמוד בדפדפן.

שימו לב להבדל, קודם, ללא Flush, אלמנט ה-CSS מתחיל להיטען בסביבות 0.72, עם Flush, הטעינה מתחילה ב-0.22, כחצי שנייה קודם לכן, אומנם זמן טעינת העמוד הוא כמעט אותו הדבר (ואם אני אחזור על הבדיקה 100 פעם, לפחות ב-20 השוואות שני העמודים ירדו באותו הזמן), אך הדף עם Flush נטען מוקדם יותר ומהר יותר כפי שתראו בפסקה הבאה.

השוואה בין שני המצבים

הסרטון הבא מציג את טעינת FMyLife ב-2 מצבים, בצד שמאל – באמצעות Flush, ובצד ימין, ללא Flush. טעינה מלאה של שני המצבים לוקחת אותו הזמן (בגלל טוויטר, FB וגוגל פלוס), אך שימו לב לטעינת התוכן בדף, בטעינה עם Flush תוכן האתר נטען מהר יותר.

לסיכום:

בפוסט הזה הצגתי שיפור של חצי שנייה בטעינת התוכן באמצעות הוספת שורה אחת ב-PHP בסוף ה-Header:

flush();

וב-Smarty:

{php}flush();{/php}

תכננו מראש את האתר שלכם לשימוש נכון בשאילתות SQL, קבלת נתונים מ-API חיצוני ע"י AJAX ובכלל, בנו אתר יעיל. 

ערב טוב,

אבי קינן.

*** בעלי שרתים: קראו את התגובה הראשונה ***

פורסם בקטגוריה האצת אתרים | 16 תגובות

כמה טראפיק מקבלים מלינק ברוטר?

בעקבות הפיגוע בבורגס בשבוע שעבר, אתר רוטר לא עמד בעומס הגולשים ולא עבד לפרקים, לאחר מכן, ביום חמישי האחרון (ה-19/7) עלתה בפורום הסקופים של רוטר (עליו כתבתי בעבר) הודעה, אחד הגולשים קרא את הפוסט בבלוג הזה וכתב עליו ונתן קישור לבלוג בפורום, בפורום רוטר התפתח דיון והיו למעלה מ-13000 צפיות להודעה בפורום רוטר.

מתוך 13,000 צפיות, 420 איש נכנסו לפוסט בבלוג וקראו אותו, מצ"ב קישור לסטטיסטיקות הבלוג בשבוע האחרון:

שבוע טוב, אבי.

פורסם בקטגוריה כללי | להגיב

אל תשתמשו ב-SSL לקבצי Javascript ולתוספים חברתיים

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

jquery:

מדובר בספריית הכתובה ב-javascript (ולכן טעינה שלה מעכבת את רינדור שאר העמוד/הורדת תכנים נוספים) שמאפשרת שימוש נרחב יותר ב-javascript, המון אתרים משתמשים ב-google לטעינת הספרייה וזה טוב:

  • לגוגל יש תשתית שרתים חזקה ומהירה (TTFB נמוך).
  • בגלל השימוש הנרחב על ידי הרבה אתרים המון פעמים הקובץ כבר נמצא ב-cache של הגולש וכך בעצם, הקובץ נטען מהמחשב וטעינת העמוד מהירה יותר.

ויש גם חסרונות:

  • במידה וגוגל עמוסים או לא מתפקדים (לעיתים רחוקות מאוד) מדובר בנקודת כשל שתתקע את כל האתר (SPOF).
  • במידה וטוענים את הקובץ מגוגל, גם אם נחבר את יתר קבצי ה-JS לקובץ אחד, עדיין יהיו 2 בקשות לקובצי JS.

הטעות שהרבה בעלי אתרים עושים, הם טוענים את הקובץ באמצעות HTTPS, ניתן לטעון את הקובץ באמצעות HTTP ואין שום השפעה על האתר אם נעשה כך. ההבדל בין HTTPS ל-HTTP (מלבד ההצפנה) היא שחיבור SSL לוקח בין 100-250 מילישניה יותר מחיבור HTTP ולכן חיבור HTTPS הוא איטי
יותר.

תוספים חברתיים:

את התוספים הנפוצים ביותר (plusone.js של גוגל, all.js של פייסבוק ו-widgets.js של טוויטר) ניתן לטעון גם באמצעות HTTP וגם באמצעות HTTPS, השימוש ב-HTTPS נועד לאפשר טעינת התוספים באתרים מאובטחים (לדוגמא: בחנות שסולקת כרטיסי אשראי), שימוש ב-HTTPS באתר שלא דורש תקשורת מאובטחת, הוא מיותר ומאט את האתר.

לסיכום:

במידה ואינכם דורשים מהגולשים שלכם לעבוד בסביבה מאובטחת, טעינת קבצי Javascript באמצעות HTTPS היא מיותרת.

פורסם בקטגוריה האצת אתרים, כללי | להגיב