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

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

March 2010 - Posts

Microsoft Dynamics CRM 4 - Set Synchronizing Client

לאחרונה נתקלתי אצל לקוח במצב כאשר בזמן פתיחה של Outlook client For CRM 4.0  מתקבלת הודעה הבא:

"You already have Microsoft Dynamics CRM for Outlook installed on another computer. Only one client computer per user can run the automated process that does bulk updates of outlook items with Microsoft Dynamics CRM Data. This client should be the computer that is most often online (such as a desktop computer) or the users primary computer. To change the Synchronizing client, on the CRM Menu, click options, and click the synchronizing tab"

אז קודם כל כפי שכתוב בהודעה יש לקבוע את ה – Synchronizing client   (CRM - > Options )

אז מה המשמעות של הודעה זו ?

לפי white paper  של קבוצת הפיתוח רק מחשב אחד שעליו מותקן CRM Outlook Client  יכול להיות מוגדר כ - "ראשי", כאשר כל השאר המחשבים יוגדרו באופן אוטומטי כ - "משניים".

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

ואם משתמש חייב לעבוד במספר תחנות ?

פתרון אחד הוא  שבמקרה זה,  ניתן להגדיר פרופיל משתמש כ - roaming profile   ואז כל התחנות יוגדרו כראשיים.

פתרון אחר, זה לעבוד עם Client  CRM Outlook  באמצעות Terminal Services או  ,Citrix, נושא שצריך לקחת בחשבון בפתרון מהסוג הזה שאם TS/Citrixמותקן בצורה תומכת  Load Balancing  אנחנו חוזרים לבעיה מקורית היות ו - Outlook Client  מותקן בכל שרת TS .

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

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

 

 

למה הכוונה במונח "ביצועים" ?

danny cohen

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

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

בפוסט הזה אני אנסה לתאר את מגוון האפשרויות והמונחים אליהם מתכוונים כאשר מדברים וחושבים על ביצועים (Performance). כמובן שאיני מתכוון להמציא את הגלגל מחדש, אלא להסתמך על הגדרות ותובנות מקובלות ונפוצות., ובראש ובראשונה על מרטין פאולר (Martin Fowler) שכלל התייחסות לנושא החשיבה על ביצועים בספרו (המצוין והמומלץ) "Patterns of Enterprise Application Architecture".

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

Response Time

זמן תגובה הוא פרק הזמן שנדרש למערכת (לרכיב ממשק המשתמש או למנגנון לוגי נפקד ממשק המשתמש, כגון API function כלשהו) להגיב לבקשה שמתקבלת ממקור חיצוני. הכוונה אינה רק לפרק הזמן שנדרש לבצע את עיבוד הבקשה (זהו ה – Processing time), אלא גם לפרק הזמן שנדרש להפיק ולשלוח את התשובה (Response) עצמה.

ישנה מידה מסוימת של אי בהירות לגבי נקודת המבט ממנה יימדד ה - Response Time: האם מנקודת המבט של מבקש הבקשה או של מקבל הבקשה ? אני אישית נוטה לאמץ את הגישה ש – Response Time נמדד מנקודת המבט של המבקש (אחרי הכל, המונח המרכזי הוא "Response"), ובהתאם לכך, תיאור ויזואלי של ההגדרה ייראה כך:

Response Time

Responsiveness -

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

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

למרות שהקונטקסט הנפוץ של Responsiveness הוא ממשק משתמש, יש מגוון תסריטים שבהם מבקש הבקשה אינו אנושי, אלא ממשק ממוכן כלשהו אשר דורש "אישור קבלה" או "דיווח התקדמות" (בעיקר בתסריטים שכוללים Long Running Processes).

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

- מתן תגובה על קבלת הבקשה (receipt)

- אספקת אינדיקציה להתקדמות (כגון מידע אשר יכול לשמש ליצירת Progress bar בממשק המשתמש) בדמות עדכון תקופתי על שינוי סטטוס בעיבוד הבקשה

- אספקת מידע חלקי ו\או אינקרמנטלי אשר למרות היותו מענה חלקי לבקשה.
כתוצאה, תינתן תגובה ראשונית בפרק זמן קצר מפרק הזמן המוגדר ע"י ה – Response time, וע"י כך ישפר את ה – Responsiveness. מונחים כגון TTFB ו – TTLB יכולים לשמש כאומדן לאספקת מידע חלקי. אפשרות אחרת היא לספק פתרון chunking של המידע (חלוקת המידע שבתגובה לחלקים, כגון pages של מידע הנפוצים בתצוגת מידע טקסטואלי, או streaming של מידע, בדר"כ בינארי כגון וידאו או אודיו).
הערה: ייתכן ובתסריטים מסוימים, ה – Response Time עצמו יוגדר כפרק הזמן עד לקבלת החלק הראשון מהמידע החלקי. לדעתי זוהי הגדרה תקינה לחלוטין, היות וכאמור, Response Time מוגדר ע"י מבקש הבקשה (או בפראפרזה על "הלקוח תמיד צודק" – הלקוח מגדיר מהו ה – Response Time)

הדוגמא הקלאסית לטכנולוגיה מוכוונת Responsiveness היא AJAX. בסופו של דבר, מטרת השימוש ב –AJAX היא שיפור ה – Responsiveness של הדפדפן. שיטת היישום של AJAX מחקה את שיטת היישום של שיפור ה – Responsiveness של טכנולוגיות Smart client כגון WinForms או WPF, והיא מתבססת על יצירת background thread אשר מנהל את פעילות משלוח הבקשה ועיבוד התגובה מאחורי הקלעים, בלא לחסום את ממשק המשתמש (דהיינו, בתסריט של הדפדפן, בלא להטריד את משתמש הדפדפן במסך הלבן המציין המתנה לתשובה משרת האינטרנט).

במובן זה, Responsivess הינו במידה רבה אחיזת עיניים: שימוש בטריקים ויזואליים על מנת לספק תחושה סובייקטיווית של Response Time מהיר יותר (לדוגמא: הצגת שעון חול, או Progress bar, או פרסומת וכו'). בפועל, לעתים קרובות אספקת Responsiveness מהיר יותר דורשת פעילויות עיבוד ותצוגה נוספות, ולפיכך יכולה לפגוע במידה מסוימת ב – Response time המדיד מבחינה אובייקטיווית (בדר"כ מדובר על פגיעה שולית).

כתוצאה, ניתן לראות בשיקול האם לעשות שימוש ב – Responsiveness כסוג של חישוב ROI: האם ההשקעה בשיפור ה – Responsiveness, והפוטנציאל לפגיעה מסוימת ב – Response Time, תוביל לתחושה סובייקטיווית של המשתמש כי ה – Response Time השתפר, במידה אשר מצדיקה את המאמץ והמורכבות הנוספים הכרוכים באספקת פתרון Responsiveness ?

Latency

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

בהפשטה, אפשר לתאר את ה – Latency כשילוב של אילוצים הנגזרים מחוקי הפיזיקה: סה"כ זמן העיבוד, וסה"כ זמן התעבורה ברשת (במערכת מבוזרת) וכן התעבורה בין רכיבי המחשב השונים. בראייה מפורטת יותר התמונה קצת יותר מורכבת היות וישנם מגוון של רכיבי ביניים (לדוגמא, במערכת מבוזרת ישנם נתבי תקשורת, רכיבי חומרה\תוכנה כגון Proxies, firewall וכדומה) ובתקשורת מקומית ישנם היבטים נוספים מעבר להעברת המידע ל – CPU או הצגתו למשתמש (כגון סנכרון cache בין מעבדים שונים בסביבה מרובת מעבדים וכדומה).

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

Throughput -

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

בדרך כלל (אך לא תמיד), ה - throughput מהווה הכפלה של מדד כלשהו מבין המדדים הקודמים (Response Time, Responsiveness או Latency) במידה מסוימת של מקביליות (parallelism) אשר נובע מיכולות חומרה או תוכנה או מנגנוני תקשורת (או שלושתם) לבצע פעילות מקבילית.

לפיכך, כאשר אני מנסה לנסח את דרישות או פוטנציאל ה – throughput, אני מתחיל באיתור המדד הבסיסי והפעילות לפיה הוא ימדד, ולאחר מכן בוחן את אפשרויות ההכפלה באמצעות parallelism. לדוגמא: אני מתחיל בבחירת מדד כגון ה - Response Time של פעילות כגון Transactions / sec. לאחר מכן, אני בוחן את אפשרויות ה - parallelism: האם יש לי אפשרות להשתמש רק ב – CPU אחד (ואז אין לי אפשרויות מקביליות בחומרה, אך ייתכן ויש לי אפשרות למקבל את הפעילות באמצעות תוכנה, כגון ע"י שימוש ב – Multi-tasking של מערכת ההפעלה), או שיש לי אפשרות להשתמש במספר רב של מעבדים, ואולי אפילו יש לי אפשרות לפצל את פעילות העיבוד בין מחשבים שונים תוך שימוש בתשתית תקשורת מתאימה (כאן אפשר להמשיך לדיון על Scale-out – ראה בהמשך בנושא Scalability).

Performance

בדר"כ אפשר להגדיר את המונח "ביצועים" (Performance) על בסיס המונחים שהוגדרו עד כה. בתסריט מסוים יוגדר Performance כ – "Response time נמוך משנייה ב – 90% מהמקרים", ובתסריט אחר יוגדר Performance כ – "Throughput גבוה מ – 100 טרנזאקציות בשנייה".

הבחירה בין אפשרויות ההגדרה השונות של המונח Performance תתבצע לרוב על בסיס שיקולי דרישות פונקציונאליות או דרישות לא-פונקציונאליות (Quality Attributes). עם זאת אפשר גם לקבוע כי הגדרת המונח Performance בהקשר מסוים תתבצע על בסיס או תוך שילוב מגוון המונחים הבאים (כגון load, efficiency או scalability מסוג מסוים). עם זאת, הנטייה בנושא היא לבסס את המונח הגולמי של Performance על הגדרות בסיסיות של Response Time ו\או throughput ו\או latency, ולאוו דווקא לכלול בהגדרה את המונחים הרחבים יותר של load ו – scalability. אלו בדר"כ ראויים להגדרה נוספת, רחבה יותר, של היבטי התנהגות המערכת.

Load

ה – Load ("עומס") הוא מדד אשר מהווה תיאור של המערכת במונחי מדד פעילות. לדוגמא: ה – Load של מערכת יכול להיות מתואר כ – "20 בקשות בשנייה", או "100 משתמשים פעילים".

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

Load Sensitivity

זהו מדד המורכב משילוב של Load ומדד נוסף כגון Response Time, ומתאר את השינוי היחסי במדד אחד בעקבות שינוי של מדד אחר. לדוגמא: "Response Time של עד שנייה אחת כאשר יש עד 100 טרנזאקציות בשנייה, ו – Response Time של שנייה אחת עד שתי שניות כאשר יש יותר מ – 100 טרנאזאקציות בשנייה".

ניתן להציג את Load Sensitivity כגרף המשלב שני צירים. לדוגמא:

Load Sensitivity

הגרף מתאר את ה – Load העולה (במונחי Transactions/second) ואת ה – Response Time המשתנה בהתאם ל – Load המשתנה. ניתן לראות בגרף את פריט המידע השימושי ביותר הנובע מ – Load Sensitivity, והוא ה"ברך" בביצועים: הנקודה שבה ה – Load משפיע על מדד הביצועים (במקרה זה, ה – Response time) במידה שמכופפת את גרף ה – Response time ביחס ל – load (כיפוף הגרף הוא הבסיס לכינוי "ברך". בגרף המצורף ניתן לראות כי ה"ברך" מתרחשת כאשר ה - Load מגיע ל ~220 טרנזאקציות בשנייה).

Efficiency

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

מדד יחסי מציין את ה- Load Efficiency ביחס למדד רצוי או מערכת אחרת. לדוגמא, מערכת אשר מספקת Response time של 5 שניות תחת עומס של 220 טרנזאקציות בשנייה, הינה מערכת פחות יעילה מכזו שמספקת Response Time של 2 שניות תחת עומס דומה.

מדד כספי יכול לציין את העלות הכספית של המערכת בחלוקה למדד Performance נתון. לדוגמא, "מערכת שעלותה 10,000$ ויכולה לעמוד ב – throughput של100 טרנזאקציות בשנייה ו – Response Time של פחות משתי שניות". אם המדד המרכזי של המערכת הוא כמות הטרנקזאקציות בשנייה, אז ניתן לומר שעלות כל טרנאקציה לשנייה הוא 100$ (תוצאת חישוב 10,000 חלקי 100 טרנקאזציות לשנייה). בדרך כלל, כאשר מגיעים לדיון מסוג זה, השלב הבא הוא ניסיון זוחל של הלקוח ליצור גרף המתאר את יעילות העלות לאורך טווח מדד הביצועים (לדוגמא, ע"י שאלות כגון "כמה תעלה לי מערכת שמסוגלת לספק 200 טרנאקציות בשנייה ב – Response Time של פחות משתי שניות ?"). בדרך כלל קשה מאוד לספק תשובות לשאלות כאלו ללא בדיקה אמפירית (שעלותה משתנה אך לרוב משמעותית).

Capacity

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

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

דוגמא למיקום לא יעיל שכזה הוא ה"ברך" שאותרה במסגרת מדידת Load Sensitivity (ראה דוגמא לעיל). בדוגמא הזו אפשר לומר שה – Capacity של המערכת הוא 220 טרנזאקציות בשנייה, היות וכל גידול ב – Load (בכמות הטרנזאקציות בשנייה) יביא לגידול לא פרופורציונלי (ולא מקובל מבחינה עסקית) של ה – Response Time.

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

Scalability -

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

האפשרויות של Scalability היו בעבר פשוטות וקלות: Scale-out לעומת Scale-up, כאשר אפשרות ה – Scale-up היוותה אמצעי מילוט מבטיח לאנשי פיתוח עצלים ("המערכת לא מספקת את הביצועים הנדרשים? בואו נרכוש חומרה חזקה יותר!"). הקפאון בגידול במהירות מעבדים, הפך את האופציה הזו ללא רלוונטית (ראה המאמר המצויין The Free lunch is over של Herb Sutter).

שתי האפשרויות שנותרו לפיכך, הן Scale-out כשימוש במספר רב של שרתים, או Scale-out כשימוש במספר רב של CPU או CPU-Cores (אפשרות זו נחשבת בעיניי ב – Scale-out היות והיא דורשת את אותם המאפיינים הבסיסיים של Scale-out למספר רב של שרתים: אפשרות לבצע partitioning של הפעילות הנדרשת, והאפשרות לבצע הפרדה של state מפעילות העיבוד עצמה).

מבין כל אפשרויות האופטימיזציה הזמינות לשיפור יכולות המדדים השונים שתוארו בפוסט זה, אני חושב שאין ספק שהמדד הקל ביותר לשיפור (לפחות בהיבטי עלות\תועלת) הוא מדד ה – Scalability. מתוך הנחה שיש בידינו מערכת שמספקת יכולת scalability טובות (בהיבטי scale-out שנדונו לעיל, והיות ויש מידע וניסיון רב כיצד לבנות מערכות כאלו, אני מאמין שזו דרישה מציאותית מאוד בימינו) אז לרוב הרבה יותר זול ומהיר "לזרוק חומרה על הבעייה" על מנת לספק פתרון לדרישות ביצועים. ההיבטים הכלכליים והמודל העסקי של Cloud Computing הופך מגמה זו לכדאית ויעילה הרבה יותר מבעבר, ולהערכתי מגמה זו רק תתחזק עם התגברות התחרות בין ספקי יכולות Cloud Computing (בדגש על ספקי IaaS ו - PaaS), וכן עם הוספת עוד ועוד CPU Cores לשרת הממוצע.

תכנים נוספים בתחומי ביצועים:

Improving .NET Application Performance and Scalability
http://msdn.microsoft.com/en-us/library/ms998530.aspx

Performance Testing Guidance for Web Applications http://www.codeplex.com/PerfTestingGuide

אליק לוין על Performance
http://blogs.microsoft.co.il/blogs/alikl/archive/tags/Performance/default.aspx

שירותי MCS בתחום:


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

Exchange Server 2010 - DAG, DAC and Site Resilience important notes

 

בתקופה האחרונה במסגרת ייעוצים של הסבות/שדרוגים מתשתית Exchange Server 2003/7 לארכיטקטורה מבוססת על Exchange Server 2010 ליוויתי וסקרתי מסמכי תכנון שנכתבו על ידי שותפים וגיליתי שיש מספר נקודות מהותיות בתפישת הארכיטקטורה בגרסה זו של Exchange שאינן ברורות מספיק, ולכן החלטתי לפרסם Blog קצר זה והפניות ללינקים חשובים שיספקו פירוט נוסף.

ב Exchange Server 2010 חשפנו יכולות שרידות וזמינות משופרות לתפקיד ה Mailbox Server, מאילו שהיו בגרסאות ה Exchange עד כה. היכולות כלולות במושג חדש המכונה Database Availability Group (בקיצור "דג" - DAG).

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

להלן איור כללי של תשתית Exchange 2010 הפרושה על פני שני Datacenters - "ראשי" (Redmond) ו"משני" (Dublin):

Datacenters and Exchange 2010 DAG

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

לרוב, בתצורה בה מוגדר Datacenter "ראשי" (פעיל) ו Datacenter "משני" (למטרות Disaster Recovery בלבד) - מומלץ יהיה להגדיר DAG יחיד, כאשר ה File Share Witness - FSW, נמצא ב Datacenter ה"ראשי".

יש לשים לב כי בתצורה זו, במקרה של כשל בתקשורת בין שני ה Datacenters, במידה והיו בסיסי נתונים פעילים ב Datacenter ה"משני" (בו לא נמצא ה FSW) - בסיסי הנתונים יבצעו Dismount ולכן לא יהיה שירות למשתמשים ב Datacenter ה"משני".

מכאן, שבמקרה שבו מעוניינים שגם שרתי ה Exchange 2010 באתר ה"משני" יהיו פעילים בשוטף (ולא רק במקרה של DR) - הפתרון המומלץ יהיה: שימוש בשני DAG (אחד עבור כל Datacenter) והגדרת ה FSW "מקומי" בכל אחד מה Datacenter. יש לשים לב, שבמקרה זה נדרשים עוד שני שרתי Exchange 2010 Mailbox Role (אחד עבור כל Datacenter, אשר ישמשו במקרה של DR באתר השני)

נקודה נוספת שחשוב להבהיר היא שבמידה והגדרתם כחלק מה DAG גם Alternate File Share Witness ומיקמתם אותו על שרת ב Datacenter "המשני", הרי שבמקרה של כשל ב Datacenter "הראשי" אותו Alternate File Share Witness אינו מתפקד כלל בצורה אוטומטית! נדרשת התערבות ידנית של מנהל המערכת, על מנת להפוך את ה Alternate File Share Witness ל File Share Witness "רגיל"!

שימו לב שהמעבר במקרה של כשל באחד מה Datacenters הוא ידני (ולא אוטומטי)!

שימו לב גם, כי נדרש גם עדכון ידני של כתובת ה IP של שירות ה CAS (הפניית ה IP Address של ה CAS Array מה Datacenter "הראשי" אל ה IP Address של ה CAS Array המצוי ב Datacenter "המשני")!

בנוסף, על מנת למנוע מצב של Split-Brain Syndrome, שעלול להיווצר במקרה שה Datacenter "הראשי" חוזר לתפקד לאחר הכשל, וה Datacenter "המשני" עדיין משרת את המשתמשים שתיבותיהם נמצאות בבסיסי הנתונים שפעלו קודם לכן ב Datacenter ה"ראשי", מומלץ להגדיר את ה DAG בתצורה המכונה: "Datacenter Activation Coordination" (בקיצור DAC). שימוש בתצורה זו ימנע מבסיסי הנתונים ב Datacenter שכשל מלבצע Mount אוטומטית.

לינקים שימושיים בנושא:

-        מידע אודות DAC ומטרתו: http://technet.microsoft.com/en-us/library/dd979790.aspx

-        מידע אודות Datacenter Switchovers: http://technet.microsoft.com/en-us/library/dd351049.aspx

בהצלחה ו"דיג" נעים,

אפי ברגמן.

 

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, מתודולוגיות פיתוח וארכיטקטורת תוכנה.