Load balance עם NGINX + PM2
-
מה הדרך הנכונה לעשות loadbalance עם PM2 ו NGINX?
אני יודע שב pm2 יש דבר שנקרא cluster mode
שזה בעצם מריץ את אותו תהליך (של nodejs) כמה פעמים (על כל CPU) ע"י שימוש ביכולת cluster של nodejs
ואיך שאני מבין (עוד לא בדקתי מספיק), כל התהליכים יכולים להאזין לאותו פורט.אז בעצם יספיק לעשות ב nginx הפניה לשרת אחד, על פורט אחד, והשרת עצמו נותן את היכולת של ה loadbalance
זה נותן גם יכולת חשובה ב PM2 שנקראת reload, שהתהליך NodeJS עושה restart מבלי להפיל אף resuest באמצע.
לחילופין, ניתן להריץ ב Pm2 כמה פעמים את אותו התהליך, על פורטים נפרדים. ולהגדיר ב nginx את ה - load balance (יש שם כמה אפשרויות לזה).
בהנחה שאני צודק בהנחותי, באיזה דרך מומלץ להשתמש?
אשמח להמלצות ולתיקונים. -
@מנצפך
רק כדי לעשות סדר ולראות אם הבנתי נכון.
אתה רוצה לבנות nginx עם %100 זמניות.
אז לכן אתה רוצה ליצור לצורך העניין 4 תהליכים מקבילים של nginx
שיאזינו לאותו פורט (איך זה יכול להיות?) או בפורטים שונים ולהעביר את התעבורה עם עוד nginx שיעביר את התעבורה לשרתים האחוריים.
וכך אם אתה צריך לבצע שינוי בnginx אתה יכול לשלוחSIGINT
במקוםkill
ובהנחה שnginx מבצע graceful stop כשהוא מקבלSIGINT
, אתה תקבל 100% זמינות.
אבל רק שים לב שתצטרך לעשות את הreload לתהליך השני רק אחרי הוא נגמר בראשון, כי לכאורה nginx מפסיק לקבל בקשות אחריSIGINT
, וגם לשים לב למשתנהkill_timeout
בPM2 , כי אם הוא מוגדר על המתנה קצרה הוא ישלחkill
אחרי כמה שניות שSIGINT
לא מגיב ואם יש לך בקשה ארוכה הוא יפול. -
א. אכן כל התהליכים יכולים להאזין לאותו פורט (זה לא באמת, יש מסטר שכנראה הPM2 יוצר שמאזין וכולם תהליכי משנה שלו והם מקבלים לעבודה בקשות שהמסטר קיבל).
ב. לא צריך לשנות כלןם בNGINX, כי זה חלוקת עומסים ברמת האפליקציה
ג. בNGINX אני חושב שגם אתה יכול לעשות ריסטרט בלי לעצור באמצע בקשה, בתנאי שאתה סוגר את התהליך בkill עדין, אני לא בטוח בזה. -
@מנצפך אני מתכוון לתהליך של נוד.
@nigun בkill יש כמה סוגים, יש בקשת סגירה בה נדמה לי הserver מטפל ומחכה לסגירת החיבורים ואז מודיע על סגירתו ואז הנוד משחרר את עצמו ונסגר, ויש את kill 9 שלא נותן ליישום בכלל זמן להתארגן, אני לא יודע פרטים מדוייקים.
@Men770 המילים יחי המלך הם לגיטמיים בחתימה ולא בהודעה עצמה, והם אכן כבר מופיעים בחתימה. מה הרעיון לכפול? אנא הימנע מכך.
-
@dovid אמר בLoad balance עם NGINX + PM2:
@nigun בkill יש כמה סוגים, יש בקשת סגירה בה נדמה לי הserver מטפל ומחכה לסגירת החיבורים ואז מודיע על סגירתו ואז הנוד משחרר את עצמו ונסגר, ויש את kill 9 שלא נותן ליישום בכלל זמן להתארגן, אני לא יודע פרטים מדוייקים.
חיפשתי על זה קצת
יש הבדל בין פקודתkill
שנועד לשלוח את כל סוגי הסיגנאלים לתהליך
לביןSIGKILL
שזה הסיגנאל למערכת הפעלה להרוג את התהליך מבחוץ, ואם רוצים לשלוח אתSIGKILL
עם שורת הפקודה צריך לשלוחkill -9
.
לחלופין אם רוצים לשלוחSIGINT
צריך לשלוחkill -2
וכן הלאה, אפשר לראות כאן עוד אפשרויות.
מקור -
@מנצפך אמר בLoad balance עם NGINX + PM2:
אני לא מבין מה הדרך שהוא גורם לכל המופעים להאזין לכל הפורטים?
מה חסר לך בהסבר הזה?
@dovid אמר בLoad balance עם NGINX + PM2:
כולם תהליכי משנה שלו והם מקבלים לעבודה בקשות שהמסטר קיבל
התהליך המרכזי משמש רק כמרכזיה (אם כך מגדירים אותו, זו לא הגדרה בהגדרה פשוט מכניסים התניה בתחילת הקוד אם הוא הרצת המאסטר תעשה כך ואם משנה אז כך).
-
למה אתה חושב ש:
@מנצפך אמר בLoad balance עם NGINX + PM2:אבל התהליך צריך להאזין לאיזשהו פורט.
מחייב
@מנצפך אמר בLoad balance עם NGINX + PM2:זה מאפשר לכולם לרוץ על אותו פורט.
זה מאזין לפורט שאתה מגדיר בהרצת האפליקציה, מה אכפת לך איך הוא מתקשר עם תהליכי המשנה?
-
@מנצפך אמר בLoad balance עם NGINX + PM2:
עומס של RAM
לא עקבתי אחרי האשכול ואני לא מכיר פתרונות של חלוקת עומסים, רק הפליא אותי המשפט הזה. מה איכפת לך איך הראם מחולק בין התהליכים, בסוף אתה תצריך אותו כמות של ראם? ריבוי תהליכים רק תשתמש ביותר ראם עבור אותם פעולות, לכאורה?
-
לסיכום:
בשביל PM2 צריך לעשות כך:
אין צורך לשנות את הקוד . יש רק להריץ את התהליך ב cluster mode.
בשביל לבצע reload ללא חשש של נפילה של בקשות חשובות באמצע (כגון ביצוע עיסקאות, או עדכונים במסד נתונים), יש להאזין ל SIGINT, ברגע שאני מקבל SIGINT, אני סוגר את השרת (את התהליך הנוכחי) לקבלת בקשות חדשות, (ע"י מתודת close), וממילא NodeJs יעביר את הבקשות לשרת השני.
חשוב להגדיר ל PM2 את הזמן לביצוע kill לאחר ה SIGINT, כי הזמן הדפולטיבי ייתכן שלא יספיק. (לכאורה אין בעיה לעשות KILL גם לאחר עשרות שניות).
במידה ואכן מבצעים עדכונים ל DB או שמבצעים שאילתות חשובות החוצה (כנ"ל), אולי כדאי להגדיר Flag גלובלי, שמראה מתי מחכים לתשובה, ולבצע timer כל עוד שהוא למעלה, ברגע שהוא למטה, אפשר לסגור את התהליך ב process.exitאשמח לחוו"ד