[קטגוריה:הודעות] [קטגוריה:ביצועים] [קטגוריה:API ופיתוח]
[תאריך פרסום]
[קישור לפוסט]FastComments מופץ כעת באופן גלובלי[/קישור]
מה חדש
לשעבר, FastComments הייתה להארכיטקטורה מאוד מסורתית עבור יישום ווב. היו לנו את שרתי האפליקציה, מסדי הנתונים, וכמה שירותים אחרים. זה היה מוזכר בשני אזורים (us-west ו-eu). אם היית בשFrance ורצית לצפות בשיחה על תגובה עבור לקוח שהוסדר במרכז הנתונים הגלובלי שלנו, הבקשות שלך היו צריכות ללכת כל הדרך ל-us-west עבור נתוני התגובה.
לא יותר! עכשיו נתוני התגובה וכל נכסי המדיה משוכפלים באופן גלובלי עבור לקוחות בפריסה הגלובלית שלנו, ועבור לקוחות בפריסה שלנו באיחוד האירופי יש לנו שלוש נקודות נוכחות באירופה שבהן הנתונים משוכפלים. הבקשות שלך הולכות לנקודה הקרובה ביותר באירופה.
איך זה עבד פעם
מלבד מסדי הנתונים שהיו להם מספר עותקים חיים בין אזורים וספקי ענן, כל השירותים היו מופצים על מופע אחד לכל סוג שירות. זה משמעותו שבכל אזור היה לנו שרת אפליקציה אחד, שרת pubsub אחד, ושרת מדיה אחד. התוכנית הייתה להגדיל באופן אנכי כל עוד יכולנו כפי שזה שומר על הדברים פשוטים. כתיבת קוד הייתה קלה - תמיד ידעת שאתה יכול "לקרוא את הכתיבה שלך" כשפונים אל מסד הנתונים. התשתית הייתה קלה, מלבד עדכוני אבטחה שלוקחים דקה של הפסקה.
הבעיה
הבעיה החלה כמובן כששחיתנו לקיבולות הגבוהות. אז אופטמנו, ולאחר מכן בעקביות היינו צריכים להגדיל את גודל המופע עבור אותו שירות.
זה החל להיווצר בגלל העלויות ב-Linode, שבו מופע של $144 הוא בערך שווה, לפי בדיקות ה-passmark שלנו, של נוד $20 מ-OVH, ואפילו אם היינו מחליפים ספקי אירוח היינו מקבלים נקודות כשל יחידות בכל מקום - וספקים כמו OVH נוטים להיות עם זמני פתרון ארוכים יותר מאשר Linode בעיות תחזוקה.
RiR :)
בשנים הראשונות שירותי PubSub ו-Media ב-FastComments נכתבו ב-Java. Java נבחרה להיחשב יחסית לביצועים גבוהים על המאמצים המושקעים, ואחרי שנים של כוונון ה-GC, ניסוי ב-G1GC, Shenandoah, ו-Z1, החלטנו שאין יותר Java. ההוצאות על זיכרון היו פשוט גבוהות מדי וכששירותים אלה היו מאוד סטטיים אחרי ההשלמה, היתרונות של Java הלכו ופגו. בנוסף, השירותים הללו נאלצו בדרך כלל להתמודד עם בעיית "ההמולה הרועמת", מה שפירושו שה-JVM מנסה להתמודד עם עומס שיא כשעדיין לא נכנס ה-JIT לפעולה. השירותים הללו היו מועמדים אידיאליים לעבור ל-C++ או Rust.
Rust נבחרה כי איננו מומחי C++ ושגיאה בקוד הרשת עלולה לחשוף נתונים של לקוח אחד ללקוח אחר. Rust עוזרת לנו למנוע בעיות מסוג זה.
רצינו לאחד את השירותים הללו בכל מקרה, אז בעוד שהיינו יכולים לעשות עוד מעבר אופטימיזציה אולי עם GraalVM, החלטנו לעבור ל-Rust ולסיים את זה.
המיגרציה לא הייתה ללא בעיות. השירותים הללו צריכים לסיים SSL, לתמוך ב-HTTP 1.1, HTTP/2, ועוד. הם עוסקים בדברים כמו ניהול מספר זרמים של נתונים במקביל, קריאת מדיה ממטמון lru דיסקי בקצה, S3, מסדי נתונים, ותקשורת ברשת. האקוסיסטמה של Java, Vertx ו-Netty, היו מאוד טובים לדברים הללו. אנו מדחפים את האקוסיסטמה של הספריות עד הגבול שלה, וחוסר הניסיון שלנו עם ספריות Rust עמדו אותנו במסלול של ניסוי וטעייה. זה גרם לכמה הפסקות, ואנחנו מתנצלים על כך.
ניסינו גם מספר מנהלי זיכרון שונים, והתמקמנו על mimalloc עבור השרתים DNS המותאמים שלנו ו-libc עבור שכבת ההעברה. איננו מריצים Nginx או Apache, אלא משתמשים בשילוב המותאם שלנו של שרת DNS מותאם שמנתב לקוחות באופן גלובלי בהתבסס על אינדקס בזיכרון שמתחדש מדי שבוע מ-Maxmind ושלב ההעברה שלנו ב-Rust שמתחזק רשת עם שאר מופעי ההעברה. ההעברה מסיימת SSL, מטפלת בעבודת pubsub, ומשמשת כ-CDN שלנו. היתרון של זה הוא פחות עומס כשמזיזים דברים בין שירותים, ופחות עומס/אבסטרקציה בתשתית. החיסרון הוא הוויזיביליות, אז מדדים טובים הם חשובים.
מבחינת הביצועים התוצאה, השירותים ב-Rust השתמשו בכ-10-30% מהזיכרון של אלו של Java, למרות כל העבודה שלנו. קראתי ספרים כמו Java Concurrency in Practice לשעשוע, אז כשהייתי לא מומחה אני יודע דבר או שניים על כתיבת שירותי JVM מהירים, וזה היה הרבה יותר קל להשיג את זה עם Rust. בנוסף, התקפות של הודעות למספר גדול של מנויים בקושי נרשמו בשימוש מעבד כאשר השירותים של JVM היו מבלים 40% מהזמן שלהם ב-GC, למרות שכתבנו את הקוד שלנו יותר כמו מנוע משחק ופחות כמו שרת טיפוסי. איני יכול לומר שאני אוהב במיוחד את Rust, אבל עבור שירותים שעושים הרבה עבודה ואינם משתנים הרבה אחרי הפיתוח הראשוני, זה מושלם. ההיגיון העסקי הראשי שלנו נשאר ב-TypeScript.
הארכיטקטורה החדשה
בארכיטקטורה החדשה אין יותר "צמתים אהובים". במקום זאת, כל שרת הוא העתק מלא עם כל השירותים ובאותה קונפיגורציה כמעט. הם כולם מפעילים את ההעברה, DNS, שרת האפליקציה, ועותק של מסד הנתונים. כל הצמתים שומרים על הצפנת דיסק מלאה עם פתיחה אוטומטית עם Dropbear.
כל שרת מפעיל את ההעברה המנתבת שמסיימת בקשות ומטפלת בהן כ-websocket, זרם http, או בקשת cdn. השרתים הללו מחוברים זה לזה וכל אחד מהם מספק מיפוי של הרשת הגלובלית לשרת ה-DNS המקומי שלה כדי לומר ל-DNS בזמן אמת היכן נמצא כל צומת חי ברחבי העולם.
יתרון של הארכיטקטורה החדשה הוא חסרון. אם לקוח באזור אחד מכה אותנו חזק, שאר האזורים נשארים זמינים.
קוד האפליקציה עכשיו חייב להיות מאוד מודע לאילו שאילתות יכולות לפגוש את הצומת הקרוב ביותר או אילו חייבות ללכת למאגר הראשי, שעשוי להיות רחוק. לעשות טעות עלול להוריד באופן קיץ בביצועים. זה גם אומר שכתיבה מכמה אזורים עלולה להיות איטית, וזה דורש כיוונון ואופטימיזציה קפדנית. עתה אנחנו עוקבים אחר תבנית פנימית בקוד שבה כל השיטות שפוגעות במסד הנתונים מקבלות ארגומנט readPreference, כך שהמזמינים עד לפסגה צריכים להחליט במפורש כיצד לבצע שאילתות.
היתרון הוא סקירה מאוד טובה אופקית לקריאות. FastComments היא מאוד כבדה בקריאה, אבל אנחנו לא צריכים לשכוח את המתחזים שלנו! המתחזים עובדים יום ביומו ברחבי העולם ואנחנו רוצים שהחווייה שלהם תישאר טובה. כחלק מהשק rollout הזה עבדנו עם כמה מהם כדי לוודא שהכלים להנחיה נשארים מהירים.
אנחנו גם יכולים לבחור במיוחד חומרה, שזה כיף ומתגמל. השרתים החדשים הם שילוב של תיבות i5-13500 ו-Ryzen 5 5600X, ו-EU על כמה Xeons ישנים יותר. במדגם שלנו כל אלה היו הרבה יותר מהירים מהשרתים היקרים יותר שחקרנו אצל ספקים אחרים. החיסרון הוא יותר עבודה בהתקנה, אבל אוטמט את זה, יחד עם ניטור SMART לדיסק עבור תקלות וכן הלאה.
לעשות דברים כאלה מאפשר לנו להמשיך להציע מחירים תחרותיים.
הגלישה
הגלישה בשבועות האחרונים כשאנחנו כותבים מחדש את השירותים ומעבירים לספקי אירוח חדשים הייתה קשוחה, תודה על הסבלנות שלכם.
במהלך הגלישה ההתחלתית המדדים שלנו הראו לנו עלייה בבקשות שנמשכו > 100ms. אנחנו מנסים לא לאפשר לבקשות רבות לקחת כל כך הרבה זמן לכל דבר.
אנחנו עדיין מבצעים התקדמות הדרגתית לשיפור הביצועים עבור כמה אזורים. תודה לכל מי שסיפק משוב עד כה.
שיקולים בעת השימוש ב-API
ה-API נשאר עקיב מאוד - אתה יכול לקרוא את הכתיבה שלך - כדי לשמור על תאימות לאחור ולשמור על דברים פשוטים עבור המפתחים. כדי לאפשר למפתחים לבחור ביצועים על פני עקביות אנו מתכננים לחשוף את פרמטר readPreference. היתרון הוא שאולי נציע גם הנחה עבור שיחות API אלו.
כל הכתובות הפומביות, כמו לשרת את תוסף התגובה הציבורי, תמיד קוראות מהמאגר הקרוב ביותר (מקומי) באותו צומת.
למה לא פשוט להשתמש ב-CDN רגיל
שיחות התגובה אינן סטטיות, הן פעילות, ויישום זרם פעיל על נתונים סטטיים ישנים גם לא עובד שכן כשאתה צופה בשיחה בתור משתמש אנונימי אתה מקבל "שיחת משתמש אנונימי". במהלך השיחה האנונימית אתה יכול לעשות דברים כמו לחסום ולדגל משתמשים אחרים, ואתה צריך להראות אם המשתמש האנונימי אהב תגובה נתונה, וכן הלאה. שיחות תגובה יכולות להיות גם חסומות מאחורי SSO, אימות, או קבוצות משתמשים.
לבסוף, הסוג של "שיפור מתקדם" שבו הנתונים הדינמיים מעודכנים לנתונים הסטטיים מה-CDN נותן לך חוויה רעה שבה תוכן קופץ או משתנה לאחר מספר שניות. נעדיף לא לעשות את זה.
מי מחזיק בנתונים שלי עכשיו
הנתונים שלך כבר לא מאוחסנים על Linode. הם משוכפלים בזמן אמת בין Hetzner ל-OVH עם הצפנת דיסק מלאה, וכל התקשורת בין השרתים האחוריים נעשית עם TLS. אנחנו שומרים על מספר מופעים מלכתחילה ב-Linode עבור פרוקסי webhook שיצאו, אבל אין נתונים או מדיה נשמרים על Linode.
לסיכום
כמו בכל שחרור מרכזי, אנחנו שמחים שהצלחנו לקחת את הזמן כדי לאופטם, לבדוק ולשחרר כראוי את השינוי הזה. FastComments אמורה להתרחב טוב יותר ולשמור על זמינות טובה יותר בטווח הארוך בעבודת זו. יידע אותנו למטה אם אתה מגלה בעיות כלשהן.
