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

בלוג היועצים של מיקרוסופט ישראל

NoSQL – Not only SQL

[אני שמח לארח שנית את שחר בר (ברזניצקי), ארכיטקט מנוסה בתחום High Scalable Applications.]

ממי לביא העלה בפוסט המצויין שפירסם את הטעות שביצירת סכמת בסיס נתונים "גנרית" על בסיס נתונים רלציוני בעל יכולות ACID. כפי שאני רואה את זה הנושא שממי העלה הוא חלק ממרחב הבעייה הכללי העוסק בשימוש בכלי הנכון למטרה הנכונה. בהקשר של Data bases, או במונח הכללי יותר של data stores, אכן עולה צורך בבסיס נתונים גנרי עבור מערכות. הצורך עצמו לגיטימי בסוגי מערכות רבות ולכן רצוי למצוא עבורו את הפתרון הנכון ביותר. כפי שממי הסביר בצורה נכונה sql server או אף Oracle Database אינם בהכרח מתאימים לסוג כזה של אכסון ואחזור מידע.

אחד הפתרונות הקיימים לצורך זה הינו בקבוצה גדולה של data stores המאוגדים כולם תחת שם נושא כללי של NoSQL. למרות שבתחילה חלק אנשים שונים בתעשייה התייחסו אל הנושא כשלילת המודל הרלציוני בחיפוש אחר מודל חדש "טוב יותר" היום ברור לרוב העוסקים בתחום שמדובר למעשה ב"לא רק SQL".

אז מהו בעצם העולם הזה של NoSQL?

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

בראשית היו לנו אתרי אינטרנט עם פעילות הולכת וגואה שדרשו עוד ועוד שרתי Database מאחוריהם כדי לעמוד בעומס (כמו שרובנו חווינו, בסיס הנתונים הוא צוואר בקבוק קלאסי). חשבו רבים וטובים שניתן בעצם להוציא לcache את המידע ולחסוך חלק ניכר מהעומס מבסיס הנתונים וכך התפתחה ארכיטקטורה מבוססת in memory distributed cache + reverse proxies for data המשתמשת רבים מהאתרים הגדולים בכל אחת מהטכנולוגיות הקיימות בשוק. עם הזמן אנשים התחילו לתהות למה בעצם אנחנו ממשיכים להחזיק מאחורה בסיס נתונים רלציוני חזק ומתוחכם כאשר אנחנו לא באמת צריכים את היכולות שלו עבור חלקים ניכרים מהאפליקציה. תחושה זו היוותה בעצם את הקרקע הפורייה לרעיונות חדשניים ו"חתרניים" שהתפתחו לכדי עולם שלם של פתרונות המאוגדים תחת השם NoSQL.

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

מרבית המוצרים הנ"ל ניתנים להתקנה הן על מערכות הפעלה של Microsoft והן על מערכות הפעלה של חברות מתחרות. כמו כן למרבית המוצרים המאוזכרים במאמר ניתן להתממשק בקלות מקוד .net הן באמצעות APIים וdrivers לעבודה ישירה והן באמצעות כלי ORM הקיימים בשוק.

ניתן לחלק את עולם המוצרים הנ"ל לפי הצורה בה רואים ומתייחסים אל המידע*:

Document stores – בקבוצה זו בולטים MongoDB, ב וcouchDB (ואפילו lotus notes יכול להשתייך לקבוצה זו).

Key value stores – בקבוצה זו מוצרים מבוססי דיסק או זיכרון. מוצרים בולטים בקבוצה זו:

Azure table storage של Microsoft, memcachedb , velocity של Microsoft, Cassandra של facebook המשמש גם את DIGG, Dynamo של amazon (ו-project voldemort שהוא מימוש הopen source לפי הwhite paper של Dynamo), TokyoTyrant ו-berkelyDB.

Multi-dimensional tabular stores – בקבוצה זו ניתן למצוא את BigTable של google (ו-HBase המבוסס על הwhite paper של BigTable) ואת HyperTable

*חשוב לציין שמדובר בחלוקה קשה מאד לביצוע מאחר ולרבים מהמוצרים בקבוצות השונות תכונות חופפות ואף ההגדרות עצמן של הקבוצות נתונות למחלוקת. למשל, רבים מגדירים קבוצה בשם record stores ומכילים בתוכה הן את Cassandra והן את hbase

המאפיינים המרכזיים של מוצרים אלו הינם:

- התייחסות פחות קשיחה למידע. במרביתם אין סכמה קבועה וניתן לשלב באותו data store (המקביל לטבלה רלציונית לצורך העניין) רשומות בעלות מבנה/סכמה שונה. למשל – אם אני מחזיק רשימה של פרופילי משתמש בdocument store לחלקם יהיו ארבעה מאפיינים בלבד ולאחרים יהיו 20 וזאת מבלי להכיל sparse data.

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

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

- המידע ברבים מהמקרים אינו מנורמל מאחר ובד"כ אין פעולת join (את פעולת Join נחליף בד"כ בפעולת map-reduce כפי שלמשל עושים באתר MySpace באמצעות פלטפורמת qizmt הכתובה ב .netוזמינה להורדה ושימוש חופשי)

- שימוש רב בbson ו-json כ-DTO.

- ישנו דגש גדול על partition-tolerance שמשמעותו היכולת לבצע חלוקה של המידע למספר nodes בד"כ באופן דינאמי מבלי לאבד מכלל היכולות המוגדרות של הdata store.

- ואולי הכי בולט - מימוש רק חלק ממרכיבי ACID ולא בצורה מלאה. למשל קיים בחלקם מימוש של eventual consistency שמשמעותו הינה "בסופו של דבר המידע שלך יהיה consistent" כאשר סופו של דבר תחום כמובן בתחום זמן מוגדר היטב. בהתייחסות לבעייה המקורית ברור שלא כדאי לתכנת מערכת כספית לATM המבוססת על מודל זה אך אין סיבה שבמימוש של רשת חברתית נתעקש על קונסיסטנטיות מיידית של המידע...

מאחורי נושא זה של מימוש חלקי בלבד של תכונות ACID עומדת תיאורית CAP ולפייה מערכת מחשב מבוזרת לעולם לא תוכל לממש את שלושת התכונות הללו יחדיו:

  • קונסיסטנטיות
  • זמינות
  • עמידות לחלוקה (partition) של המידע

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

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

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

שירותי MCS רלוונטיים

  • (PDF) שירות ניתוח פערי ארכיטקטורה
  • (PDF) שירותי ניהול מחזור חיים של אפליקציה – ALM
  • Brancning & Merging - פוסט המשך

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

    Basic Plan

    image

    כללי אצבע לבחירת המודל:

    • ­בכל פעם משחררים גרסה אחת ויחידה של המוצר/מערכת
    • ­כל הלקוחות משדרגים באותו הזמן לגרסה החדשה
    • ­כל הבעיות והתוספות יראו אור בגרסה הבאה

    Development – נועד לעבודה על הגרסה הבאה.

    • ­ ניתן לייצר מס' ענפים ע"פ חלוקה למודולים,יכולות עסקיות, צוותים וכו'.
    • ­ כל ענף הוא ענף מלא של Main. הכוונה היא לא לבצע branching למס' קבצים חלקי.
    • ­ בצע Merge מ- main בכל פעם שיש build מוצלח. תשאף לכל יום יומיים.
    • ­ בצע Merge אל ה- Main ע"פ קריטריונים ברורים ועמידה ברמת האיכות שנקבעה

    Release  – משם תשחרר את הגרסה הראשית

    • ­ענף מלא של Main
    • גרסת המוצר/מערכת תשוחרר מענף זה
    • שינויים או תיקונים שבוצעו על Release יכולים לעלות בחזרה ל- Main. אי ן לבצע Merge מ- Main
      שכן הוא כבר עשוי להכיל שינויים של הגרסה הבאה.
    • ­עבור הגרסה הבאה, יש לייצר ענף Release חדש.

    Standard Plan

    image

    כללי אצבע לבחירת המודל:

    • ­ יש צורך לתמוך בעדכוני גרסאות (Service Packs)
    • ­ קיים צורך לפתח במקביל service pack לגרסה נוכחית ויכולות עבור הגרסה הבאה
    • ­ קיים צורך להקפיא גרסה לצורך בקרה או ע"פ תקינה מסוימת

    בנוסף על האמור לגבי Basic Plan:

    Service Pack

    • נוצר כענף של main
    • ­נועד לצורך תיקון ומתן שירות לגרסה שיצאה ועלתה לאוויר
    • שינויים שבוצעו ב- Service Pack יכולים לעלות ל- Main ע"י merge
    • לגרסה הראשית הבאה, יש לייצר ענף Service Pack חדש.

    Release

    • נוצר כענף של Service Pack
    • נועד לשמור על גרסה סטטית שלא משתנה
    • לאחר שחרור הגרסה, הענף הופך ל- read-only
    • יכולות להיות מס' גרסאות שיצאו מאותו ענף Service Pack

    Advanced Plan

    image

    כללי אצבע לבחירת המודל:

    • יש צורך לתמוך במקביל במספר גרסאות שונות של release, Service Packs ו- Hot Fixes.
    • ­Service Packs נוצרים כענפים של Main
    • Hotfix נוצר שענף של Service Pack
    • ל- Service Pack יכולים להיות מס' ענפי Hotfix
    • Release נוצר כענף של ה- Hotfix
    Posted: Mar 14 2010, 01:44 AM by cobyp | with 3 comment(s)
    תגים:, , ,
    Generic DB or Who needs DB?

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

    בסיס נתונים כזה יכיל בדרך כלל טבלה בשם Entities או Entities_Types, אשר מכילה את הגדרת הישויות השונות, טבלה בשם Entity_Fields המכילה הגדרות של השדות השונים בכל ישות, וטבלה בשם Entity_Data, המכילה אוסף שדות, בדרך כלל מסוג String, המייצגים את נתוני הישויות עצמן. בנוסף נמצא בבסיס נתונים כזה בדרך כלל גם טבלה בשם Entity_Links המכילה את הקשרים בין הישויות השונות.

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

    אז זהו שלא.

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

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

    2. אין דרך לאכוף, ברמת בסיס הנתונים, את סוגי הנתונים הנשמרים. כל הנתונים מאוחסנים כ- String, ומבחינת בסיס הנתונים אין משמעות ל- Meta Data המוגדר.

    3. לא ניתן לעשות שימוש בכלי DB מתקדמים יותר כגון Partitioning, משום שכל הנתונים נשמרים בטבלה אחת.

    4. לא ניתן לעשות שימוש ב- Foreign Keys ו- Constraints, וממילא ה- Data Integrity, שהוא ליבו של בסיס הנתונים המודרני, נפגע קשות.

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

    6. כלי ORM מודרניים כדוגמת Entity Framework, LINQ 2 SQL, NHibernate לא יודעים להתמודד בצורה טבעית עם בסיס נתונים שמתוכנן כך.

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

    למעשה, משמעות העיצוב הנ”ל הינה ויתור מלא על יכולות ה- DB, ובניה של DB חליפי על גביו. ואם זה המצב – לא חבל להוציא כסף על בסיס נתונים מודרני? יש לנו File System מצוין שאפשר להשתמש בו! אמנם אין לו מפתחות, אינדקסים, בדיקות תקינות וכו’ – אבל מי צריך אותם?! אנחנו כבר נבנה את בסיס הנתונים שלנו לבד!

    ואתם יודעים מה? אל תאמינו לי. אני מזמין אתכם לראות מה יש ל- Tom Kyte, Oracle VP להגיד בנושא. הוא אולי מתחרה של מיקרוסופט, אבל יש דברים שבהם הקונצנזוס חוצה גבולות וחברות. הקישור להלן מפנה למצגת שהוא העביר לפני כשנה בשם Oracle Database Worst Practices. שימו לב מה יש לו להגיד בשקפים 16-22. (גם השאר מעניין…)

    http://www.ukocn.com/forums/database-dbms/dbms-technical-network/tom-kyte-oracle-database-worst-practices

     

    אז לסיכום – אם כבר החלטתם לעשות שימוש בבסיס נתונים (ורוב הסיכויים שכך החלטתם…) עשו בו שימוש כמו בבסיס נתונים, ולא כמו ב- File System. אל תבנו טבלאות Meta Data – לבסיס הנתונים כבר יש כאלה משל עצמו, הוא לא צריך עוד.

    זכרו – לא תמיד הפתרון הפשוט ביותר הוא המוטעה…

    Troubleshooting SQL Server 2005/2008 Performance and Scalability Flowchart

     

    לפני כמה שבועות הייתי נוכח בפגישה נכבדה של DBAs והייתה חגיגה ממש J.

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

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

    חכמים אמרו (אלה שהקשבתי להם...) , שעם עובדות לא מתווכחים!

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

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

    הקליקו עליי להורדה.

    בהצלחה.

    WCF 4 Routing Service Multicast sample
    danny cohen

    לדעתי, Routing Service הוא אחת מהתכונות היותר מעניינות שהתווספו ל – WCF 4.0. למרות שניתן לפתח Routing Service עצמאי (ראה לדוגמא את המאמרים של Michele Leroux Bustamante's  תחת הכותרת "Building a WCF Router") עדיין הגיוני יותר לבחון שימוש ב- Routing Service שמגיע OOTB עם .NET 4.0.

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

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

    אז בפוסט הזה אני אציג sample שמיישם את יכולת ה – Multicasting של WCF 4.0 Routing service. אך לפני שנקפוץ לתוך הקוד, אני מעוניין להסביר איך הסיפור הזה משתלב בתמונה הכללית של תבניות (patterns) הרלוונטיות לנושא.

    Routing Service ומפת התבניות הרלוונטית

    האפשרות לבצע routing מבוסס על בסיס תכני ההודעה (CBR, או Content Based Routing) היא יכולת שכלולה ברשימת התבניות הבסיסית של מוצרי ESB שונים (הבה נכנה אותם "ESB Usage Patterns").

    האיור הבא מתאר את מפת התבניות הרלוונטית ל – ESB, והיחסים ביניהם (ישנה נטייה מסוימת לקרוא בשמות שונים לתבניות דומות, אבל הבה לא ניכנס כרגע לדיוני נומנקלטורה משמימים). מידע נוסף בנושא תבניות בתחום האינטגרציה ניתן למצוא באתר http://www.eaipatterns.com  של Gregor Hohpe's, ובאופן כללי אני ממליץ בחום על ספרו בנושא.

    ESB-CBR Patterns - OneWayService sample

    ניתן ליישם את כל התבניות הנ"ל באמצעות ובשילוב Routing Service (אחרי הכל, Routing Service הינו רכיב המרחיב את WCF.

    למטרות ה – smaple המתואר בפוסט הזה, אני מתמקד (בהתייחס לתרשים הנ"ל) ביכולות הבסיסיות של Routing Service וביישום של יכולות ה – multicast, תוך יישום תבנית שניתן לכנותה בהקשר זה כ – scatter-only (להבדיל מ – scatter-gather המופיע בתרשים).

    דרך נוספת להציג את הקונטקסט של ה – sample, היא ע"י סקירה של היכולות הבסיסיות של Routing Service עצמו, כפי שהן מתוארות בתרשים הבא:

    Routing Patterns

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

    אז, הבה נעשה קצת multicasting:

    תיאור ויזואלי של מה שמבצע ה – sample ניתן לראות בתרשים הבא:

    Routing Service Multicast

    הקליינט שולח הודעה דרך ה – Routing Service תוך שימוש בכל binding זמין (במקרה זה אני עושה שימוש ב – WsHttpBinding, אך כל binding אחר יכול לשמש למטרה זו). ה - Routing Service מעביר (routes) את ההודעה למספר כלשהו של שירותים (destination services) אשר לקיומם הוא מודע באמצעות הגדרות בקונפיגורציה (באמצעות קוד או קבצי קונפיגורציה). העברת ההודעות לשירותים מתבצעת תוך יישום פילטרים או חוקים המגדירים את מדיניות ההעברה (באמצעות מודל של Message Filters – ראו הרחבה בהמשך הפוסט).

    ל - Routing Service יש גם את היכולת להגדיר ולעשות שימוש ב – Backup Endpoints המוגדרים ספציפית לכל נקודת שירות (Service Endpoint). במקרה של תקלה במשלוח הידיעה לנקודת שירות זו או אחרת, ה – beckup endpoint  המקושר אליה יקבל את ההודעה במקומה, כיישום failover.

    שימו לב שלא כללתי בדוגמא זו יישום של UDP transportation, למרות שהדבר מתבקש בכל דיון שעוסק ב – multicasting. ישנו יישום לדוגמא של UDP כ – WCF Sample, וניתן לעשות בו שימוש כ – binding בהקשר זה, אם כי זה כבר נושא לפוסט אחר.

    ועכשיו - הגיע הזמן לראות קצת קוד.

    The Client:

    נתחיל עם ה – contract שמשתפים ביניהם ה – client ו – services. מדובר על contract שמיושם כ – interface פשוט למדי. שימו לב כי יישום multicast דורש יישום של one-way, היות ומדובר על תבנית של scatter-only ולא של scatter-gather מסוג כלשהו.

    Multicast Interface

    ה – contract הבא משותף בין ה – client וה – service. שימו לב של – Routing Service אין כל היכרות עם ה – contract הספציפי הזה, היות והוא אמור להיות אגנוסטי ל – contract או ה – interface הספציפי שאיתו עובדים ה – client ו – services מולם הוא מתקשר.

    כאמור, ה  -client שולח הודעת one-way רגילה למדי ל – Routing Service, ללא כל מודעות או התאמות לכך שמדובר ב – routing service ולא ב – service עצמו. ההתאמה היחידה הנדרשת היא כמובן שהכתובת (address) שבה ייעשה שימוש ה – client תהיה כתובתו של ה - Routing Service.

    ב – interface שלעיל ניתן לראות שנשלח גם מידע על זמן משלוח ההודעה (כ - ticks). מטרת הפרמטר היא לאפשר ניטור של משך זמן משלוח ההודעה מה – client ל – service דרך ה - Routing Service. המידע מוצג הן ע"ג ה – client console והן ע"ג ה – service console (צילומי מסך בהמשך הפוסט). חשוב לציין כי נתוני זמני הביצועים יהיו אמינים ומדויקים רק כאשר גם ב – client וגם ה – service ממוקמים ע"ג אותו שרת\מחשב (ה - Routing Service יכול להיות ממוקם ע"ג שרת מרוחק).

    Multicast client code

    The destination service:

    למטרות ה – sample יושמו מספר endpoints על גבי ה – service, כאשר כל endpoint מיישמת binding מסוג אחר. היישום מבוצע במתודה בשם "GenerateEndpoints".

    Multicast endpoints code

    מעבר לזאת, ה – service הוא רגיל למדי. החומר המעניין נמצא, כצפוי, ב - Routing Service.

    The Routing Service:

    בצד של ה - Routing Service, החומר המעניין מרוכז בעיקר במתודה בשם "ConfigureRouterViaCode". מרכז הפעילות במתודה הוא סביב אובייקט בשם RoutingConfiguration אותו יוצרים, מגדירים ומזינים לתוך ה – ServiceHost.

    Multicast routing configuration code

    סדר הפעילות, בקצרה, הוא:

    1. יצירת אובייקט RoutingConfiguration
    2. יצירת רשימת ה – endpoints של ה – services אליהם יש לשלוח הודעות (הרשימה תאוחזר, מן הסתם מתוך מאגר מידע כלשהו, כגון בסיס נתונים זה או אחר).
    3. הוספת כל endpoint לרשומה משלו באוסף ה  - Filter Table, תוך ציון ה – Message Filter המתאים (הרחבה בהמשך).
    4. אופציונאלית, ניתן להגדיר לכל endpoint גם backup endpoint תואם.
    5. לסיום, הוספת ה - RoutingConfiguration ל – routing behavior, והוספת ה – routing behavior ל – ServiceHost.

    חשוב להדגיש כי ה - Routing Service  אינו מודע ל – contract type שאיתו עובדים ה – client ו\או ה – service. ה - Routing Service עושה שימוש ב – contract ייעודי שמטרתו לאפשר העברת ההודעות באופן שמתעלם מה  -contract הספציפי ומודע רק ל – Message Exchange Pattern (ה - MEP) בו נעשה שימוש.

    .Multicast routing contract code

    ב – sample זה, אנו עושים שימוש ב – ISimplexDatagramRouter, אשר, כפי ששמו מרמז, מהווה interface פשוט לייצור contract שמיועד להעברת הודעות כ – datagram (כלומר: בסמנטיקה של one-way). ניתן לעשות שימוש במספר contracts / interfaces אחרים של Routing Service ליישום sessions (ISimplexSessionRouter), וכן ליישום Request/Reply MEP (IRequestReplyRouter).

    כברירת מחדל ב – sample זה, ה - Routing Service מעביר את כל ההודעות לכל ה- services המוגדרים ב – routing configuration. זאת, מכיוון שנעשה שימוש בדוגמא שלעיל ב – MatchAllMessageFilter. יש עוד מגוון של Message Filters אחרים שמגיעים OOTB, אך גם מאוד קל ליישם Custom Message Filters באופן עצמאי. ב – sample כלולים שני Custom Message Filters אשר מאפשרים לבצע routing בהתאם לבדיקת והשוואת ערך ה – SOAP Action header וכן ע"י השוואות ערכים ב – Message Body (היישום אינו אופטימלי בהיבטי ביצועים, אך ניתן לתקן זאת בהשקעה נמוכה יחסית, ובהתאם לתסריט הספציפי הנדרש ליישום).

    לדוגמא, דוגמאת הקוד הבאה, מציגה את ה – ActionContainsMessageFilter הכלול ב – sample.

    Multicast custom MessageFilter code

    ניתן להפעיל message filter מסוים באמצעות שורת הקוד הבאה, הממוקמת (כהערה שניתן לבצע לה uncomment) במתודה ConfigureRouterViaCode שצוינה לעיל:

    Multicast custom MessageFilter using in code

    הפעלת שורת קוד זו תאפשר העברה רק של הודעות אשר ב – SOAP Action header שלהם מופיעה המילה "Write".

    ניתן להגדיר את ה – Routing Service באמצעות קובץ קונפיגורציה סטנדרטי (app.config או web.config), אך ב – sample בחרתי לבצע זאת בקוד מסיבות שכבר צוינו. עם זאת, ב – sample כלול קובץ קונפיגורציה לדוגמא אשר יכול להדגים זאת.

    הפעלת ה - Sample:

    ה – sample כולל שלושה executables:

    • client console
    • Routing Service console
    • service console

    מסיבה זו, ה – solution הוגדר להפעלה של Multiple Startup Projects:

    Multicast solution startup settings

    חשוב לשים לב שה – client מוגדר ש – Start without debugging. הסיבה לכך היא באג אשר מתיו סניידר, ה – Program Manager של Routing Service, הסב את תשומת ליבי לקיומו. כאשר פרויקט WCF נמצא ב – debug mode, ה – debugger מוסיף custom SOAP header ייחודי להודעה. במקרה של Routing Service, היות וגם ה – client וגם ה - Routing Service עצמו יכולים להיות תחת debugger, יתבצע ניסיון גם ב - Routing Service עצמו להוסיף את אותו ה – custom SOAP header, אך מכיוון שהוא כבר שם, תתרחש שגיאה. המעקף לכך הוא פשוט מאוד – הפעלה של ה – client או ה - Routing Service שלא תחת ה – debugger, כפי שמתבצע ב – sample זה.

    לחיצה על F5 מפעילה את 3 ה – executables ומאתחלת את הרכיבים, כאשר ה – client ממתין לאישור פעולה של המשתמשע"י לחיצה על enter.

    לחיצה על enter בחלון ה – client תשלח הודעות אתחול ל - Routing Service ותספק היזון חוזר לגבי הביצועים ההתחלתיים.

    Multicast client init message

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

    בצד השירות, ניתן לראות כי הודעה אחת אשר נשלחה ע"י ה – client, הופצה ע"י ה - Routing Service למספר רב של endpoints מסוגים שונים, בהתאם להגדרות ב - RoutingConfiguration settings.

    Multicast routing init message

    עם משלוח ההודעה השנייה ע"י ה – client, ניתן לראות את הביצועים הסטנדרטיים של הרכיבים לאחר האתחול:

    Multicast client 2nd message

    והנה התוצאה במסך ה – service:

    Multicast routing 2nd message

    קוד מקור של ה - sample:

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

    מקורות מידע נוספים על Routing Service:


    danny cohen שמי דני כהן ואני ארכיטקט ויועץ בצוות MCS Israel, ומתמחה במערכות מבוזרות, Cloud Computing, מתודולוגיות פיתוח וארכיטקטורת תוכנה.

    SCSF - גרסה חדשה

    לפני כשבועיים אמר לי לקוח שהוא שוקל לעבור ל – dotnet framework 4 עם VS2010. ללקוח מערכת winform שמפותחת על בסיס smart client software factory (SCSF) ועלתה השאלה האם העובדה שהמערכת מפותיחת על בסיס SCSF מונעת את המעבר.

    שאלה זו רלוונטית כמובן לכל מי שפיתח/מפתח מערכת מבוססת SCSF ולכן מצאתי לנכון לפרסם זאת כאן…

    בימים אלו עומלים ב- P&P על גרסה חדשה של SCSF. גרסה זו אינה שונה במהותה מקודמותיה והיא מפותחת מעל entlib 4.1 ומטרתה לאפשר עבודה ב – VS2010.
    כלומר, מי שרוצה להמשיך לעבוד ב- framework 3.5 אבל עם VS2010, הגרסה החדשה תתן לו מענה.

    אך מה אם אני רוצה לעבור ל- framework 4.0 ול – entlib 5?
    במקרה כזה, יהיה עליכם לבצע מספר התאמות (לא גדולות – בעיקר references) בקוד של SCSF ולקמפל.

    חשוב לציין – המועד הרישמי לשחרור הגרסה הוא 30 באפריל.

     

    בהצלחה,
    טל

        

    שירותי MCS רלוונטיים

  • (PDF) שירות ניתוח פערי ארכיטקטורה
  • (PDF) שירותי ניהול מחזור חיים של אפליקציה – ALM
  • חמשה דברים שלא ידעתם על מדיסון - SQL Server 2008 PDW

    השנה מיקרוסופט תצא עם גירסא חדשה של מסד הנתונים  SQL Server 2008 R2 המיועדת למחסני נתונים ענקיים. המוצר החדש מבוסס על ידע שנרכש מחברה בשם DataAllegro שמיקרוסופט קנתה לפני כשנה וחצי.אז כמה דברים שכדאי לדעת:

     1.      יש כבר היום ל DataAllegro לקוחות עם 350TB - בגירסא של SQL Server היעדים יותר אגרסיבים

     2.      הארכיטקטורה דומה לזו של Teradata (שהיה לי בגלגולי הקודם הכבוד לנהל את ההתקנה הראשונה שלה בארץ)

     3.      המערכת היא Scale out, Share Nothing, High Availabale - הכל By Design

     4.      המערכת מיועדת אך ורק למחסני נתונים - לדוגמא - אין תמיכה ב Stored Procedures

     5.      יש לפחות 4 לקוחות מתעניינים בשוק הישראלי, אבל עם מישהוא רוצה להצטרף ל TAP - יש סיכוי (קטן)

     

      
    על מחשוב בענן, TCO, ומונים חשמליים בפרברי הולנד
    danny cohen

    לפני כשבוע נערך כנס P&P Summit, שבמהלכו הרצה יוחניו פצ'ה (Eugenio Pace), אחד מהמובילים בנושא מחשוב ענן ו - S+S, מספר הרצאות בנושא Azure בפרט, ומחשוב בענן בכלל.

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

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

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

    מדוע ?

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

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

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

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

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

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

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

    ומה הקשר למחשוב בענן ?

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

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

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

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

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

    לעומת זאת, במחשוב בענן מסוג Platform as a Service, רכיבי החומרה, התקשורת, אחסון המידע ותשתיות התוכנה נכללות במסגרת שירותים עליהם משלמים על בסיס צריכה ("pay as you go"). המרכיב המשמעותי היחיד שעל ארגון הלקוח לספק הוא רכיבי התוכנה המהווים את האפליקציה עצמה. כלומר: את שורות הקוד שנכתבו ע"י איש הפיתוח. משמעות הדבר, היא שבמחשוב בענן, ישנה האפשרות לזהות את הקשר הישיר שיש לשורות קוד על העלות הכוללת של המערכת. במצב כזה, ברור שיופעל לחץ הולך וגובר על אנשי הפיתוח להוריד את עלויות התוכנה אותה הם מפתחים.

    אך כיצד יכולים אנשי הפיתוח להוריד את עלויות השימוש במחשוב בענן ?

    במשפט אחד: מודעות להיבטים הכספיים של התוכנה אותה הם מפתחים.

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

    לדוגמא:

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

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

    אך מהו ההיבט הכספי של מספר שורות קוד אלו ?

    שירותים כגון ה – Windows Azure Storage מחייבים על בסיס נפחי שימוש, נפחים אלו נמדדים לרוב ע"פ כמויות החומרה (VM's) בה ייעשה שימוש, נפחי מידע (GB אחסון בחודש), תעבורת מידע (GB מידע נכנס או יוצא ברשת התקשורת החיצונית) וכן טרנזאקציות מידע (כמות פעולות הכתיבה והקריאה שמתבצעות מול מאגר המידע), וכאן חבויה יכולתו של איש הפיתוח להשפיע באופן משמעותי – לטוב ולרע – על עלויות המערכת.

    Windows Azure TCO Calculator

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

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

    הבה נניח, למטרת ההשוואה, שבמקום לבצע שמירה עבור כל טרנזאקצייה, איש הפיתוח יבחר לאגור את הטרנזאקציות, ולשמור אותם למאגר המידע כ – bulk update של 1,000 רשומות בכל פעולת שמירה. זוהי פעולה מעט יותר מורכבת, אך הפער בנפחי הטרנזאקציות הוא פי 1,000, וכתוצאה, גם העלות בצריכת שירותי הטרנזאקציות גדלה פי 1000, ולרוב ההשפעה חורגת גם להיבטי עלויות שירותים נוספים.

    לדוגמא, בצילום המסך שלעיל, חישוב פשוט (באמצעות מחשבון ה – TCO של Windows Azure, ניתן לראות ששימוש לא מבוקר בטרנזאקציות שמירה וכתיבה ל – Windows Azure Storage יכול להוביל לעלויות גבוהות מאוד באופן יחסי (בדוגמא שלעיל: 12,000$ לשנה, ובערך שני שליש מעלות אחסון המערכת ב – Windows Azure). אם יחליט התוכניתן לעשות שימוש מושכל בטרנזאקציות, ניתן לצמצם את העלויות הללו באופן משמעותי ביותר.

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

    משמעויות:

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

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

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

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

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

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

    ולסיכום:

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

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


    danny cohen  שמי דני כהן ואני ארכיטקט ויועץ בצוות MCS Israel, ומתמחה במערכות מבוזרות, Cloud Computing, מתודולוגיות פיתוח וארכיטקטורת תוכנה.

    Branching & Merging - האם אתה באמת צריך את זה? רוב הסיכוי שכן...

    לעבודה עם branches יש כמובן תקורה נוספת. הנק' הבאות אמורות לסייע לכך בקבלת ההחלטה.

    "אצלנו לא עובדים על גרסאות במקביל..."

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

    שאלות הכוונה:

    האם אני צריך לתמוך בפיתוח מקבילי?

    • פיתוח מס' גרסאות של המוצר
    • טיפול בתקלות בגרסאות ששוחררו (Service Packs & Hot Fixes)

    האם אני צריך סביבות פיתוח מבודדות?

    • הוספת שינויים מהותיים – breaking changes
    • Refactoring
    • ייצוב

    אם ענית בחיוב לחלק מן השאלות, אתה צריך לשקול מעבר למודל של branching.
    ישנם מס' מודלים עליהם תוכל לבסס את מבנה עץ ניהול התצורה בהתאם לצרכים הייחודיים שלך.
    כאשר אתה בוחן את המודל יש להביא בחשבון את הנושאים הבאים:

    • גודל קבוצת הפיתוח, מבנה הצוותים ואופי העבודה
    • הצורה בה משחררים גרסאות לייצור והאם יש צורך לתמוך ב- service packs ואולי אף hot fixes

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

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

    1. Basic Plan

    clip_image001

    2. Standard Plan

    clip_image002

    3. Advanced Plan

    clip_image003

    שירותי MCS רלוונטיים

  • (PDF) שירותי ניהול מחזור חיים של אפליקציה – ALM
  • (PDF) שירות ניתוח פערי ארכיטקטורה
  •  

    Posted: Feb 17 2010, 01:20 PM by cobyp | with 5 comment(s)
    תגים:, , ,
    שיפור תפוקת צוות הפיתוח ללא עלויות – חלק ב'

    בפוסט קודם בנושא, דיברתי על האופציה שבכל פעם שמבצעים checkout יתבצע get latest version, כך שכברירת מחדל תמיד נעבוד על עותק מעודכן של הקובץ.

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

    Build & Continuous Integration

    מה זה Build?

    כאשר אני מדבר על build אני מתכוון לתהליך Build המנוהל ומטופל ע”י TFS.
    במה שונה תהליך Build מ – Build שאנחנו מבצעים ב – (Ctrl+F5) Visual Studio?
    ביצוע ה – (Ctrl+F5) build הוא רק חלק בתהליך build שמנוהל ע”י TFS. בתהליך ה – Build מתבצעות מספר פעולות בסיסיות:
    - שליפת הקוד המעודכן משרת ה – (get latest version) TFS
    - ביצוע build
    - הרצת Unit Tests
    - העתקת התוצרים לספריה מסויימת
    - יצירת ושליחת דוח מסכם

    כמובן שניתן להוסיף/לשנות פעולות.

    על מנת ללמוד יותר על נושא של TFS Builds ראה…

     

    מה זה Continuous Integration?
    הרעיון הוא ביצוע בדיקות אינטגרציה של הקוד של האפליקציה שלנו באופן שוטף וסיסטמתי.

    איך?
    עיקר בעיות האינטגרציה קורות כאשר מבצעים שינוי במודול A, אבל משתמשים בתוצרים שלו (dlls) במודול B. מי שמפתח את מודול B לא יודע שהיה שינוי ב- מודול A וממשיך לפתח מול dll שאינו מעודכן.

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

    איזה מזל!!! ניתן להגדיר לתהליך ה – build לרוץ בכל פעם שמתבצע checkin. מאחר ותהליך ה- build מבצע get latest version לפני כל ריצה, נוכל לקבל אינדיקציה מיידית על בעיית אינטגרציה.

     

    ושוב, בהנחה שצות הפיתוח עובד בסביבת Team System, אתם חוסכים הרבה כאב ראש, זמן וכסף וזה לא עולה כלום…

     

    ועוד דבר אחד…
    הרבה פרוייקטים/ צוותי פיתוח שעבדתי איתם מאוד רצו לבצע תהליכי build אבל לא ידעו איך… התהליך מאוד פשוט וניתן ללמוד גם כאן.
    כמובן שאם למישהו יותר נוח ליווי “אנושי”, תמיד אשמח לסייע :-)

     

    בהצלחה,

    טל

     

    חומר נוסף:

    Team Foundation Build Walkthroughs

      

    שירותי MCS רלוונטיים

  • (PDF) שירות ניתוח פערי ארכיטקטורה
  • (PDF) שירותי ניהול מחזור חיים של אפליקציה – ALM
  • Dynamics CRM Workflows

     

    אחת היכולות המובנים ב - Dynamics CRM  היא מנוע workflow, באח, הפגישות נשאלתי האם ניתן לבנות פתרון load balancing  לתהליכי WF במקרה וקיימים יותר מ platform role בודד.

    אז על מנת לענות על השאלה בוא נבין איך המנוע WF עובד לפחות ברמת על

    אז מה קורה שמגדירים WF:

    1. נוצרת רשומה בטבלת WorkflowBase בבסיס הנתונים ORG_MSCRM

    2. הגדרת שלבים שונים ב - WF גורם לעדכון עמודות ברשומה.

    לאחר הגדרות יש לבצע publish :

    1. WF עובר תהליך קומפילציה.

    2. DLL נשמר ב- PluginAssemblyBase.

    3. Plug in מיוחד נרשם עבור פעולה שתריץ אתה WF במערכת.

    טוב, אז מה קורה שפעולה הקשורה ל - WF ספציפי מתבצעת:

    1. Plug in מיוחד הרשום עבור פעולה זו תהפוך את ה - WF הרלוונטי לרשומה בטבלה AsyncOperationBase

    2. AsyncService שולף מספר WF-ים ומריץ אותם במקביל.

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

    טוב, זה ברמת על,אבל מתאור זה ניתן להבין שב - Dynamics CRM  קיימת יכולת מובנת להריץ תהליכי WF במקביל על מספר שרתים בהם מותקן AsyncService  ו - Load Balancing מתבצע על בסיס "תפוסה" של Pool  , כלומר בשרת העמוס יותר, Pool  יתרוקן לאט יותר והשרת פנוי יותר ישלוף WF הבאים.

     

    שירותי MCS רלוונטיים

    Architecture Styles / Patterns
    danny cohen

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

    "כיצד (או האם) ניתן לחזות מראש את המידה שבה הפתרון נותן מענה לדרישות, ולעשות זאת בשלב מוקדם ככל האפשר ?"

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

    שאלה ראשונה: מענה לאיזה סוג של דרישות ?

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

    את מידת המענה של הפתרון לדרישות פונקציונאליות קל (יחסית...) לבחון מבחינה טכנולוגית. "תופסים" את הדרישות האלו באמצעות תסריטים (scenarios) ו – use cases (או themes, epics ו – user stories , תלוי במתודולוגיית הפיתוח). האתגר בדרישות אלו הוא בדרך כלל אתגר של התנהלות ופוליטיקה ארגונית (השאלה "מהי הפונקציונליות הרצויה" תלויה לעתים קרובות באופי הארגון המפתח מאשר בצרכי המשתמש הסופי), בשיקולים של מאפייני המשתמשים (רקע וניסיון, ציפיות מוצהרות ולא-מוצהרות להתהגות המערכת, ציפיות סמנטיות, עומס קוגניטיבי סביר) ועוד.

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

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

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

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

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

    וכאן נכנסים לתמונה ה – Architecture Styles.

    ההגדרה ה"רשמית" של architecture styles (עד כמה שניתן למצוא הגדרות רשמיות במקצוע עמו ארכיטקטורת תוכנה, שעדיין נמצא בתהליכי התגבשות), היא:

    "A set of principles for a family of systems that determines the vocabulary of components and connectors that can be used in instances of that style, together with a set of constraints on how they can be combined"

    (מתוך המאמר המומלץ בחום "Introduction to Software Architecture" של David Garlan and Mary Shaw מ – 1994. מאמר שאפשר לשייך לו לא מעט השפעה בהיסטוריה של מקצוע ארכיטקטורת תוכנה).

    ישנו דמיון רב בין Design Patterns לבין Architecture Styles (הכינוי הנפוץ "Architecture Patterns" מעיד על כך). עם זאת מדובר במשפחות שונות של תבניות (Patterns) שגם ממוקמות ברמות שונות בהיררכיה של ניתוח ואפיון מערכות תוכנה (רמת הארכיטקטורה לעומת רמת העיצוב – design – של המערכת). בגדול, אפשר לתאר את ה – architecture styles כתבניות בעלות נפח והשפעה מערכתית גדולים יותר (לעתים, הרבה יותר) מאשר Design Patterns.

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

    שאלה שלישית: כיצד בוחרים את ה – Architecture Style המתאים ?

    לכל Architecture Style יש מגוון מסוים וידוע מראש של מאפיינים אותם הוא מספק (במידה זו או אחרת). מאפיינים אלו ניתנים לניסוח כאותם Quality Attributes, הידועים כדרישות לא-פונקציונאליות. דוגמא אחת היא ה – Pipes and Filters architecture style (ה - style החביב עלי), שמאפשר לספק Quality Attributes כגון: Configurability, Composeability, Manageability, Reusability, Testability ועוד (הגדרת ה – Quality Attributes הנ"ל אינה ב – scope של הפוסט הנוכחי, אך ניתן ללמוד יותר בקישורים המצורפים).

    וכאן אנו מגיעים לנקודה המרכזית –

    היכולת לבחון ולבחור Architecture Styles בהתאם למידת התאמתם ל – Quality Attributes (הדרישות הלא-פונקציונאליות) של המערכת, היא זו המאפשרת להמחיש כיצד פתרון ארכיטקטוני מספק מענה לדרישות אלו.

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

    מידת ההתאמה ל – quality attributes נובעת מהמאפיינים המובנים והידועים מראש של ה – Architecture Styles השונים (כאן בא לידי ביטוי הדמיון הרבה בינם לבין Patterns בכלל). הניסיון הרב שנצבר במימוש ה – Architecture Styles השונים מספק מידע רב לגבי יתרונותיהם וחסרונותיהם בהתייחס למגוון של תסריטים, וכן, עצם השימוש במונחים אחידים (vocabulary) מאפשר תקשורת יעילה מול ארכיטקטי תוכנה אחרים על מנת לאסוף המלצות, תובנות, הערות והארות בשלב מוקדם ככל האפשר בתהליך הניתוח האפיון.

    כל זאת, בלי לזלזל או להתעלם מחשיבות הרבה שיש למימוש בפועל של ה – Architecture Style על היכולת לספק מענה לדרישות השונות.
    לאחר צמצום האפשרויות ובחירת מספר
    Architecture styles שמועמדים לאימוץ במסגרת הפתרון הארכיטקטוני, מומלץ (מלשון "חובה" J), לבחון מאפיינים מעשיים, מדידים ומוחשיים של פתרונות אפשריים שמממשים Architecture Style שמועמד לשימוש. היות ורוב ה – Architecture Styles מומשו במסגרת Framework או מוצר זה או אחר, וזמינים לשימוש כ"קופסא שחורה", עולה השאלה של מידת ההתאמה של המוצר (או הרכיב, או התשתית וכו') לתסריט הספציפי עבורו מנסים לספק מענה. כמו תמיד – אלוהים נמצא בפרטים הקטנים (והשטן גם).

    ולסיכום -

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

    קישורים למקורות מידע נוספים בנושא -

    HTH,

    דני.


    danny cohen  שמי דני כהן ואני ארכיטקט ויועץ בצוות MCS Israel, ומתמחה במערכות מבוזרות, Cloud Computing, מתודולוגיות פיתוח וארכיטקטורת תוכנה.

    מיקרוסופט: הגיע הזמן לשאול את השאלות הקשות
    danny cohen

    בשבוע הבא, במסגרת כנס P&P Summit, אני מנחה את ה – ask the experts" session", במהלכו יתאספו אנשי P&P ו – MCS לפאנל שיענה לשאלות המנחה והקהל.

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

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

    וכאן אני מעוניין לבקש את עזרתכם:

    מהן השאלות הקשות באמת שאתם מעוניינים לשאול את חברי הפאנל ?

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

    אז זה הזמן לשאול את השאלות האלו.
    בתגובות לפוסט הזה אתם מוזמנים לכתוב את השאלה\ות שאתם מעוניינים לשאול את הפאנל.

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

    השאלות הטובות שיועלו, יועלו בפני הפאנל והקהל, בליווי קרדיט מלא לשואל\ת השאלה.
    כמו כן, אני מבטיח כי אעשה כמיטב יכולתי על מנת לספק מענה מיטבי לכל שאלה שתעלה בתגובות לפוסט שיישלחו לפני ה –
    P&P Summit.

    בקיצור - בואו נשאל שאלות שיגרמו לחבר'ה של P&P ו - MCS להזיע! J

     בתודה מראש,

    דני.


    danny cohen  שמי דני כהן ואני ארכיטקט ויועץ בצוות MCS Israel, ומתמחה במערכות מבוזרות, Cloud Computing, מתודולוגיות פיתוח וארכיטקטורת תוכנה.

    Posted: Feb 04 2010, 06:30 AM by Danny Cohen | with 1 comment(s)
    תגים:
    ארכוויז מס’ 6 – איך למנוע סוסים טרויניים ברכיבי .Net שלי?

    Alik Levin     פיתחתי רכיב ואני מעוניין לוודא שבזמן ריצה לא השחילו לי איזה סוסון טרויני. אשפרי?

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

    אפשרי בערבון מוגבל. למה בערבון מוגבל? כי באבטחת מידע אין הבטחה מוחלטת – זה עניין של להעלות את הרף עוד ועוד.

    תסריט מס’ 1 – הפעלת רכיב בצורה של Early Binding

    כדי שרכיבים יזהו אחד את השני Net Fx כולל המצאה שנקראית Code Access Security או בקיצור CAS. מדובר על ניהול ואכיפת הרשאות שלא מבוססות משתמש [ל-CAS לא אכפת מי המשתמש]  אלא ניהול הרשאות על בסיס זהות של רכיב. ישנם הרבי מאפייני זהות של רכיב והכי חזק ביניהם הוא Strong Name. אז כדאי מאוד לחתום את הרכיבים ע”י SNK.

    image

    כמבון שיש את העניין של ניהול SNK בצורה מאובטחת – זה מכוסה ע”י Delayed Signing.

    לא עניין גדול – חתמתי על הרכיב שלי ע”י SNK והוספתי Reference אליו מרכיב אחר ובנייתי את האפליקציה. תהליך הבנייה כלל גם הצמדה של מאפיני SNK בין הרכיבים. בזמן ריצה ה-CLR מזהה את הצימוד הזה ומוודא שהקשר לא נשבראיך אפשר לשבור אותו?למשל, ע”י כך שהרכיב שלי הוחלף ע”י רכיב אחר אך דומה וללא SNK שלי. במקרה של החלפה ה-CLR יעיף את הרכיב הזדוני ויחד איתו את האפליקציה שלי כולל רישום ל-Event Log.

    אחלה! נראה פשוט – חותמים עם SNK והכול סבבה במקרה של Early Binding. מה קורה אם אני מרים את הרכיב ב-Reflection? הרי ישנם הרבה מקרים בהם ישנו שימוש מאוד מורחב ב-Reflection כמו במקרה של Provider Design Patterns או בשם אחר Abstract Factory Design Pattern.

    תסריט מס’ 2– הפעלת רכיב ע”י Reflection ללא בדיקת חתימה

    הקוד הבסיסי להרמת הרכיב בעזרת Reflection הוא דומה לזה:

    Assembly asm = Assembly.LoadFrom("TrustedComponent.dll");
    Type myType = asm.GetType("TrustedComponent.MyBusinessComponent");
    IBusinessComponent myComponent = 
                  (IBusinessComponent)Activator.CreateInstance(myType);
    Console.WriteLine(myComponent.PerformBusinessAction(Guid.NewGuid().ToString()));
    Console.ReadLine();

    הקוד הזה יצליח בכל מקרה – עם SNK וללא SNK.  וזה מכיוון שהרכיב מורם בצורת Late Binding. לרכיב המרים אין שום ידע מוקדם לגבי הרכיב המורם.

    מסקנה – מי שעובד עם Reflection להרמת רכיבים בצורת Late Binding חסוף לתקיפות של סוסים טרויניים. עם או בלי SNK.

    ראה הוזהרת!

    תסריט מס’ 3– הפעלת רכיב ע”י Reflection עם בדיקת חתימה

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

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

    //GET STRONG NAME FOR THE LOADED ASSEMBLY
    StrongName sn = GetStrongName(assembly);
    
    StrongName myStrongName = null;
    
    //GET CURRENT APPDOMAIN STRONG NAME
    IEnumerator enumerator = (IEnumerator)AppDomain.CurrentDomain.Evidence.GetEnumerator();
    enumerator.Reset();
    while (enumerator.MoveNext())
    {
        if (enumerator.Current.GetType().Equals(typeof(StrongName)))
            myStrongName = (StrongName)enumerator.Current;
    }
    
    
    if (!sn.PublicKey.Equals(myStrongName.PublicKey))
    {
        throw new ApplicationException("SPOOFED!!");
    }
    static StrongName GetStrongName(Assembly assembly)
    {
        if (assembly == null)
            throw new ArgumentNullException("assembly");
    
        AssemblyName assemblyName = assembly.GetName();
        // get the public key blob
        byte[] publicKey = assemblyName.GetPublicKey();
        if (publicKey == null || publicKey.Length == 0)
            throw new InvalidOperationException(String.Format("{0} is not strongly named", assembly));
        StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
    
        // create the StrongName
        return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
    }

    אחלה! עכשיו אפשר לנשום לרווחה, לא? :)

    תסריט מס’ 4 – Link Demands

    אני, הרכיב התמים, לא רוצה שיפעילו אותי כל מי שבא לו אז אני אסמן את עצמי עם SNIP – קיצור של StrongNameIdentityPermission. וואו, כתבתי את זה! שימוש ביכולת הזו מעלה רף הגנה מפני הפעלה לא מורשית של רכיבים שלי [התסריט ההפוך מאלה שדיברתי עליהם קודם]. הנה לך הסבר מצוין איך להשתמש בזה -

    Using the StrongNameIdentityPermissionAttribute

    חשוב לציין ש-SNIP הוא לא תרופה אולטימטיבית מפני תקיפה של סוסים. במיוחד בסביבה שהיא Full Trust – ה-SNIP לא מזיז ל-CLR במקרה הזה בכלל. Full Trust Means Full Trust

    חשבת פעם להגדיר Custom Trust Level? זה יכול לעזור לך עם SNIP.  דרך נוספת לכתוב קוד דומה לזה בתואר בתסריט 3.

     

    איך אתה היית מונע תקיפה של סוסים טרויניים על הקוד .Net?

    שירותי MCS שאני מדלוור

    חומר רלוונטי

     

    שמי אליק לוין ואני מתרכז ב- Architecture, Security, and Performance באפליקציות Net.

    בזמני הפנוי אני מפתח את עצמי בתחומים רבים אחרים.

    This template is made with PracticeThis.com plugin for Windows Live Writer

    על Caching, על ETag ומה שבינהם

    יש לכם אתר אינטרנט שמתארח ב – IIS6 ונמצא מאחורי NLB והדפים שלכם לפעמים עולים לאט ולפעמים יותר מהר ?!
    יכולות להיות מספר סיבות להתנהגות (מעצבנת) שכזו. אני רוצה לדבר כאן על גורם אחד חמקמק…
    (ממליץ לקרוא פוסט קודם שעוסק בנושא של caching ל- static contents).

    ETag

    אז מה זה Etag?
    בקצרה – חלק מפרוטוקול HTTP. השרת מייצר ETag Header שאמור לייצג “גרסה” של ה- resource שאותו הוא מספק (בד”כ רלוונטי יותר ל- static contents – תמונות, JS וכיו”ב) והדפדפן משתמש ב- Header הזה לבדיקת caching.
    ה”גרסה” של resource, בד”כ, מיוצגת ע”י תאריך עדכון של ה- resource.

    אז איפה הבעייה?
    נניח שיש לי תצורה של שני שרתי IIS מאחורי NLB. אני מבצע request לדף – page1.aspx וה- NLB מפנה אותי לשרת א’. בתוך הדף יש “קבצים” מקושרים – תמונות, JS וכו’. הדפדפן מוריד גם אותם משרת א’ ושם עותק ב- cache המקומי.
    בפעם הבאה שהדפדפן מבקש את הדף page1.aspx הוא צריך שוב את ה”קבצים” המקושרים, הוא בודק האם הם קיימים ב- cache המקומי שלו וכשהוא פונה לשרת לקבל את הקובץ המקושר, הוא מוסיף ב- request את ה – ETag של הקובץ מה – cache. השרת בודק האם ה – Etag שנשלח ב – request זהה ל – Etag השייך ל- resource המתאים על השרת.
    אם זהה – מחזיר HTTP 304, אחרת, מחזיר לדפדפן את הקובץ המלא.
    בהנחה שיש לי שרת אחד, אחרי הפנייה הראשונה לדף, כל שאר ה – static content יגיע מה – cache, שכן השרת יזהה שה – ETag זהה.

    טוב, אז מה הבעייה? הרי אם שמתי לדוגמא, את אותו קובץ תמונה על שני שרתים, ה-ETag יהיה זהה בשניהם, שהרי לשניהם אותו תאריך עדכון אחרון…

    אז ככה…
    ב – IIS הערך של ה – ETag בנוי משני חלקים בערך במבנה הבא: ComputedValue:ChangeNumber.
    ComputedValue – זה הערך שהשרת מייצר לפי תאריך עדכון אחרון.
    ChangeNumber – זהו ערך קבוע.

    OK, ובכל זאת איפה הבעייה?
    ב – IIS6, הערך של ה – ChangeNumber לא בהכרח זהה בכל שרת…, לכן, הערך של ה – ETag כולו, עלול להיות שונה עבור אותו קובץ בשני שרתים שמאחורי NLB אחד. כך שלמרות שלכאורה ה- resource שנמצא ב – cahce של הדפדפן עדכני, אם הערך הקיים ב – cache שייך לקובץ משרת א’, אם ה – NLB מפנה אותי ב – request אחר לשרת ב’, במקום לקבל את הקובץ מה – cache, הקובץ ירד מהשרת.

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

    אז אחרי שהבנו (אני מקווה) את מקור הבעייה, בואו נדבר על פתרונות:

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

    2. לעבור ל – IIS7 – למה? ב – IIS7, כברירת מחדל, הערך של ה – ChangeNumber הוא 0. ומאחר ואני מניח שאף אחד לא מתעסק עם הערך הזה, ניתן להניח שכל השרתים ייצרו את אותו ETag לאותו דף.

    3. לעדכן בכל שרתי ה – IIS6 את הערך של ה – ChangeNumber לערך זהה. איך? ככה.

    יש לכם בעיות אחרות/נוספות עם caching? עם ביצועים באפליקציה שלכם? אתגרו אותי.

    בהצלחה,

    טל

     

    שירותי MCS רלוונטיים

  • (PDF) שירות ניתוח פערים ושיפור ביצועים
  • (PDF) שירות תכנון וניתוח בדיקות ביצועים
  • (PDF) סדנת פיתוח מערכות מונחה ביצועים
  • More Posts Next page »