מה זה NodeJS ולמה שיעניין אתכם?

קצת על NodeJS וכיצד הוא יכול להועיל לכם?

shutterstock

כותב הפוסט הוא עדי ברון, ארכיטקט JAVA בכיר ומומחה Node.js בטיקל.

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

ל-NodeJS אני מגיע בעקבות המלצה של חבר, שאני מאד מעריך, כשאני חסר מוטיבציה לחלוטין. אחרי שהבנתי שמדובר בכתיבת אפליקציות שרת בעזרת ג'אווה-סקריפט, ובהתחשב בעובדה ששבעתי נסיונות כושלים בתחום הזה בשנים שקדמו (Mozilla Rhino, Aptana Jaxer) קשה היה לי להאמין שיצא מזה משהו אמיתי. אילולא הנסיון הקודם (והמאד מוצלח) שהיה לי עם פלטפורמות מעולם הג'אווה (Apache MINA, JBoss Netty) שעושות גם הן שימוש ב-I/O אסינכרוני, סביר להניח שהייתי עושה את הטעות ומוותר.

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

NodeJS על קצה המזלג

בהגדרה, NodeJS היא פלטפורמה שנבנתה מעל מנוע הג'אווה-סקריפט של גוגל, V8, ומטרתה להוות כלי לפיתוח אפליקציות רשת שעוסקות בטיפול אינטנסיבי במידע, בזמן אמיתי, ושממעטות בחישובים. במילים אחרות – הרבה I/O ומעט CPU. היא מבוססת על מודל של אירועים (events) ועושה שימוש בספריות I/O אסינכרוניות.

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

1

הקטע שמעל כתוב ב-PHP ולקוח מתוך קוד המקור של WordPress. מתבצעת בו שאילתא אחת מול בסיס נתונים (wpdb$) שתוצאותיה מיושמות במשתנה myrows$. דוגמא סטנדרטית ומאד נפוצה שסביר להניח מוכרת למפתחי אפליקציות שרת. אם כך, מה בכל זאת לא בסדר?

התהליך שמריץ את קטע הקוד הזה (בין אם זה Thread או Process או כל דבר אחר) ימתין עד קבלת התשובה בחזרה מבסיס הנתונים, כאשר באותו הזמן הוא לא עושה כלום, ורק אז יריץ את השורות שמטפלות בתוצאה. הגיוני, אבל לוקה בחוסר יעילות. נשאלת השאלה – למה לא לשחרר את אותו התהליך כדי שיעשה דברים אחרים בזמן שהוא ממתין? מה בעצם עוצר אותנו מלכתוב את הקוד באופן הבא:

2

 

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

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

באחת מההרצאות שלו הציג ראיין דוהל (Ryan Dahl), היוצר של NodeJS, את הטבלה הבאה, שמודדת במספר מחזורי מעבד את הגישה אל הזיכרון, הדיסק, הרשת, וכו':

Screen Shot 2013-10-15 at 4.34.44 PM

סביר להניח שבבדיקה על המחשב שלכם המספרים יהיו שונים, אבל העיקרון הוא זהה והכוונה היא להדגיש כמה יקרה (במונחים של זמן עיבוד) ההמתנה לפעולות I/O.

לולאת אירועים (Event Loop)

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

ביסודה, לולאת אירועים היא תור של פונקציות. בכל זמן נתון מבוצעת פונקציה אחת בלבד עד לסיומה ואז נשלפת הפונקציה הבאה. מאחר ומדובר ב-thread אחד, חשוב לשים לב שהפונקציות יהיו קצרות ותכליתיות על מנת שלא "יתקעו" את הלולאה. בפורמט הזה אנו מעבירים את ההתעסקות עם I/O ו-threads ל-NodeJS ומספקים פונקציה שתיקרא בתום התהליך ובאופן הזה חוסכים לעצמנו כאבי ראש כמו גישה למידע משותף במקביל (בעיה מוכרת מעולם ה threads).

3

העניין הוא ש NodeJS אינה הפלטפורמה הראשונה שמציעה מימוש לרעיון הזה וחוץ מזה, אם מדובר בטריק כל כך טוב שאפשר לצמצמם אותו עד כדי thread אחד, איך זה שלא כל העולם רץ להשתמש בו?! הנה שתי סיבות לדוגמא:

חינוך – הכתיבה הסנכרונית מוטמעת בתוכניות לימוד ובספרים. קחו דוגמא קלאסית לקוד שיופיע בשלבים המוקדמים בלימוד קלט/פלט:

4

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

5

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

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

ג'אווה-סקריפט כשפת מימוש

ג'אווה-סקריפט מגיע למשחק הזה עם כמה ייתרונות חשובים:

  • האסינכרוניות מובנית בשפה וניתן לראות שימוש נרחב בה, לדוגמא: קריאות Ajax.
  • עבור משתמשי השפה, הפורמט של של פונקציות callback הוא עניין של שיגרה, ואלו שלומדים אותה מורגלים מהיום הראשון להשתמש בו.
  • לא קיימות ספריות I/O (מאחר ועד להולדתו של NodeJS לא היה צורך) ולכן קל יותר להקים קהילה של קוד פתוח שכותבת ספריות אסינכרוניות עבור NodeJS.

NodeJS בעולם האמיתי

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

הפרוייקט בו אני משתתף בימים אלו עושה שימוש ב-ElasticSearch וב-MongoDB, שמתחיל בשאילתות מצד משתמש הקצה ומעביר את הערכים שנשלפו כמו שהם בחזרה. במקרים כדוגמאת זה, כאשר העבודה נעשית כולה בג'אווה-סקריפט ו-JSON (ממשק המשתמש, ElasticSearch, ו-MongoDB – לכולם ממשק מהסוג הזה) הגיוני יהיה להעביר את הפונקציונאליות לשרת NodeJS ולהוריד את הנטל מהשרת המקורי (במקרה המדובר הוא כתוב בג'אווה, שסובלת קשות מעניין התרגום של אובייקטי JSON – לג'אווה – ל-JSON), וזו בדיוק האפשרות שאנחנו בוחנים כעת (עם סבירות גבוהה למימוש).

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

סיכום

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

אני מזמין אותך להצטרף לקבוצת המיטאפ: Full Stack Developers Israel (המנוהלת ע"י Tikal), בה תוכל להמשיך ולהעמיק את הידע בנושא זה ואחרים ע"י טובי המומחים. יתכן ותמצא עניין באחד מאירועים אלו: Javascript.everywhere ובסדנת Angular.js.

קרדיט תמונה: code via Shutterstock.

הכתבה בחסות Tikal

הכתבה בחסות Tikal

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


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


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


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


טיקל היא נותנת החסות לקבוצת המיטאפ : Full Stack Developers Israel. קבוצה זו מתמקדת באתגר החדש של כל מפתח, לשלוט בכל שכבות האפליקציה והפיתוח: front-end, back-end, database/store, infrastructure and server operation.

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

Tikal

צוות המומחים של טיקל יעזרו לכל צוות פיתוח לסיים כל משימת פיתוח בזמן ובאפקטיביות גבוהה. החל מהתאמה ומעבר לטכנולוגיות חדשות, דרך תכנון ובניית פרוייקטים ואופטימיזציה בתחומי: JAVA, Javascript, Ruby, ALM & .NET

הגב

9 Comments on "מה זה NodeJS ולמה שיעניין אתכם?"

avatar
Photo and Image Files
 
 
 
Audio and Video Files
 
 
 
Other File Types
 
 
 
Sort by:   newest | oldest | most voted
Dor
Guest

Great post that summarize the subject in simple words.

לירן
Guest

מעניין.

אך אתה בטוח שבדוגמא עם ההמתנה לDB, בזמן ההמתנה, THREAD אחר לא יקבל את המעבד? (מאין Context Switch פנימי בין הThread-ים)

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

עדי
Guest

לירן,

אתה צודק, אבל מדובר בשיטה שונה לחלוטין.
בעולם ה Threads, אמנם יעשה Context Switch וה CPU יעשה עבודה אחרת.
העניין הוא שעדיין יהיו קיימים הרבה Threads, ואלו מהם שמבצעים I/O ימתינו ללא מעש.
תחזוקה של Threads היא דבר יקר, ולכן כשמדובר בקלט/פלט עדיף להמנע מלהחזיק משאבי מערכת שסתם ממתינים. בנוסף, בעולם ה Threads קיימת גם בעיית הגישה למידע משותף.
NodeJS מציע דרך אחרת להתמודד עם Concurrency.

אלעד
Guest

אני מאמין שלירן צודק,

שרתי web בדר"כ משתמשים במספר גדול של threads ותהליך (לדוגמא: שרת Apache).
זה מאפשר "להסתיר" את פעולות ה-I/O ולספק מקביליות גדולה – לראייה Apache הוא שרת הפופולרי בעולם.
החיסרון במודל הזה הוא שהוא גורם להרבה context switches שזו פעולה יחסית יקרה.

בנוסף, יתרון זה לא תלוי רק בשפה, לדוגמה, אם שרת ה-web שלך פועל בצורה אסינכרונית, אז תקבל תוצאה דומה למה שאתה מקבל ב-node.js ללא תלות בשפה בה אתה משתמש.
למשל שרת nginx הוא שרת web פופולרי שפועל בעקרון event-driven, שמשתמש במעט thread-ים שמבצעים משימות באופן א-סינכרוני.

יונתן שקד
Guest

פוסט קולח ומעניין ואפילו מובן (לאחד כמוני שלא כותב קוד :)

john
Guest

לא רואים את התמונות בכתבה.

עדי
Guest

ניסית דפדפן אחר?

ארז
Guest

אכן לא רואים. chrome, IE

מיכאל
Guest

ממליץ להשתמש בexpress.JS עם NODE.JS

wpDiscuz

תגיות לכתבה: