מחשוב ללא שרתים עם AWS Lambda, חלק 1

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

בעקבות הסקירה הכללית, תקבל מבוא מעשי ל- AWS Lambda, שנחשב בעיני רבים כפתרון הבכורה מבוסס Java עבור מחשוב ללא שרת כיום. בחלק 1, תשתמש ב- AWS Lambda כדי לבנות, לפרוס ולבדוק את פונקציית Lambda הראשונה שלך ב- Java. בחלק 2, תשלב את פונקציית Lambda שלך עם DynamoDB, ואז תשתמש ב- AWS SDK כדי להפעיל פונקציות Lambda ביישום Java.

מהו מחשוב ללא שרת?

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

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

מה עולה AWS למבדה?

בזמן כתיבת שורות אלה, שכבת המחירים של AWS למבה מבוססת על מספר הוצאות להורג ומשך הביצוע:

  • מיליון ההוצאות להורג הראשונות שלך בחודש הן בחינם, ואז אתה משלם 0.20 $ למיליון הוצאות להורג לאחר מכן (0.0000002 $ לבקשה).
  • משך הזמן מחושב מרגע שהקוד מתחיל לבצע ועד שהוא מחזיר תוצאה, מעוגל למאה ms הקרובה ביותר. הסכום שנגבה מבוסס על כמות ה- RAM שהוקצה לפונקציה, כאשר העלות היא $ 0.00001667 לכל שנייה ג'יגה-בתים.

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

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

סטיבן היינס

הנה בקליטת המודל מודל הביצוע ללא שרת:

  1. לקוח מגיש בקשה לפלטפורמת המחשוב ללא שרת לבצע פונקציה ספציפית.
  2. פלטפורמת המחשוב ללא שרת בודקת תחילה אם הפונקציה פועלת באחד מהשרתים שלה. אם הפונקציה עדיין לא פועלת, הפלטפורמה טוענת את הפונקציה ממאגר נתונים.
  3. לאחר מכן הפלטפורמה פורסת את הפונקציה לאחד השרתים שלה, שמוגדרים מראש עם סביבת ביצוע שיכולה להריץ את הפונקציה.
  4. הוא מבצע את הפונקציה ולוכד את התוצאה.
  5. זה מחזיר את התוצאה ללקוח.

לפעמים מחשוב ללא שרת נקרא Function as a Service (FaaS), מכיוון שהפרוטרוליות של הקוד שאתה בונה היא פונקציה . הפלטפורמה מבצעת את הפונקציה שלך בשרת משלה ומתזמנת את התהליך בין בקשות פונקציה לתגובות פונקציה.

שירותי ננו, מדרגיות ומחיר

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

שירותי ננו

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

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

שירותי מיקרו לעומת ננו שירותים

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

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

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

מדרגיות

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

תמחור

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

AWS למבדה למחשוב ללא שרת

AWS למבה היא פלטפורמת מחשוב ללא שרתים המיושמת על גבי פלטפורמות שירותי האינטרנט של אמזון כמו EC2 ו- S3. AWS Lambda מצפין ומאחסן את הקוד שלך ב- S3. כאשר מתבקשת להפעיל פונקציה, היא יוצרת "מיכל" תוך שימוש במפרט זמן הריצה שלך, פורסת אותה לאחת ממופעי ה- EC2 בחוות המחשוב שלה ומבצעת פונקציה זו. התהליך מוצג באיור 2.

סטיבן היינס

כאשר אתה יוצר פונקציית Lambda, אתה מגדיר אותה ב- AWS Lambda, תוך ציון דברים כמו סביבת זמן הריצה (נשתמש ב- Java 8 למאמר זה), כמה זיכרון להקצות לה, תפקידי ניהול זהות וגישה והשיטה לה לבצע. AWS Lambda משתמש בתצורה שלך כדי להתקין מכולה ולפרוס את המכולה למופע EC2. לאחר מכן הוא מבצע את השיטה שציינת, לפי סדר החבילה, המחלקה והשיטה.

בזמן כתיבת שורות אלה ניתן לבנות פונקציות למבדה ב- Node, Java, Python, ולאחרונה, C #. למטרות מאמר זה נשתמש בג'אווה.

מהי פונקציית למבדה?

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

מצבי ביצוע ללא שרת

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

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

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

בנוסף לתגובה לקבצים שהועלו ל- S3, ניתן להפעיל lambdas על ידי מקורות אחרים, כגון רשומות שהוכנסו למסד נתונים של DynamoDB וזרמת מידע אנליטי מ- Amazon Kinesis. נבחן דוגמה שמציגה את DynamoDB בחלק 2.

AWS Lambda מתפקד בג'אווה

עכשיו שאתה יודע קצת על מחשוב ללא שרתים ו- AWS Lambda, אני אלווה אותך בבניית פונקציית AWS Lambda בג'אווה. 

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

יישום פונקציות למבדה

אתה יכול לכתוב פונקציה למבדה באחת משתי דרכים:

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

הדרך הקלה ביותר ליישם פונקציית LWS של AWS היא להשתמש בממשק מוגדר מראש. עבור Java, תחילה עליך לכלול את ספריית הליבה הבאה של AWS Lambda בפרויקט שלך (שים לב כי דוגמה זו משתמשת ב- Maven):

 com.amazonaws aws-lambda-java-core 1.1.0  

Next, have your class implement the following interface:

Listing 1. RequestHandler.java

 public interface RequestHandler { /** * Handles a Lambda function request * @param input The Lambda function input * @param context The Lambda execution environment context object. * @return The Lambda function output */ public O handleRequest(I input, Context context); } 

The RequestHandler interface defines a single method: handleRequest(), which is passed an input object and a Context object, and returns an output object. For example, if you were to define a Request class and a Response class, you could implement your lambda as follows:

 public class MyHandler implements RequestHandler { public Response handleRequest(Request request, Context context) { ... } } 

Alternatively, if you wanted to bypass the predefined interface, you could manually handle the InputStream and OutputStream yourself, by implementing a method with the following signature:

 public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ... } 

The Context object provides information about your function and the environment in which it is running, such as the function name, its memory limit, its logger, and the amount of time remaining, in milliseconds, that the function has to complete before AWS Lambda kills it.