DCSIMG
Implements bridge pattern with wcf - הבלוג של צביקה פאר

הבלוג של צביקה פאר

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

Implements bridge pattern with wcf

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

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

ל Contract החדש אין תאימות חד חד ערכית ברמת הקריאות כלומר חלק מהקריאות של ה Client  היו צריכות מספר קריאות בContract של ה Server החדש חלק היינו צריכים לשמור ב Cache  על מנת לאגד מספר קריאות מה client לקריאה אחת בServer וכד.

1

 

חשבנו על 3 פתרונות אפשריים

פתרון 1 מערכת חיצונית

לכתוב או לקנות מערכת חיצונית שהינה מאין biztalk sever  אשר יבצע את פעולת התרגום .2

 

 

 

יתרונות

מבחינת decoupling מאוד גבוה בין מנגנון ההמרה לאפליקציה , השינוי היחיד שנדרש לבצעו באפליקציה זה החלפת ה address  של ה wcf server .

אפשרות ניטור של המידע הזורם + העבודה המתבצעת באותו מתאם .

תמיכה יכולת גידול לעתיד לdevice ים או שיטות תקשורת שונות .

חסרונות

הבעיה שצריך לתחזק עוד אפליקציה \ service  שאיננו חלק אינטגרלי מהאפליקציה .(תיעוד התקנה קיטלוג )

לקנות אפליקציה חיצונית עולה כסף .

Hop  נוסף של מידע שאין בו צורך . המידע נשלח ל wcf service  ולאחריו ל עמדה הנוספת. 

 

פתרון 2 השיטה הסינית

שיטת הquick and drity  לאתר את כל המקומות בקוד שפונים לwcf client  ולשתול בכל המקומות switch ים של האם לשלוח בintrerface החדש או הישן . + להוסיף את כל הלוגיקה בתוכנה עצמה של ה Client .

יתרונות

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

חסרונות

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

כמובן שאפשר לעשות את זה יותר אלגנטי ולא להשתמש בSwitch אלא שימוש ב Factory   שיחזיר Iterface  ל ממשק .

 

הפתרון ה 3 Wcf custom channel

פתרון באמצעות Custom protocol channel שכתבנו שתפקידו לתרגם את ההודעות .

יתרונות

פתרון שהינו מאוד decoupled  אין צורך לפתוח אף אחד מהתוכנות . אפשר באמצעות קונפיגורציה להכיל אותו .

 לא נוצר עוד hop  מיותר

מאתגר מקצועית

אפשר באמצעותו ללמוד wcf  לעומק

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

חסרונות

מאוד technology aware  כלומר מבוסס על יכולות ההרחבה של wcf  ותלוי ביכולות האלו . ומכיוון ש wcf איינו קוד פתוח ניתן להיתקע עם memory leak בעיית ביצועים או חלקים שבלתי ניתנים למימוש .

 

Wcf channels

התשתית של wcf  מכילה ערימה של channels  המתפקדים כ chain of responsibility

דומה מאוד ל ndis filter drivers  .

3

 

 

בין כל החלקים של ה channel  זורמים אוביקטים מסוג Message .

הMessage

מורכב מ Headers  וPayload  של המידע (הAction  והפרמטרים שלה ).

כל channel  יכול להוריד להוסיף או לשנות את ה header ים .

כמו כן ה Channel יכול לשנות את ה payload כלומר את המידע עצמו שעובר ב Message

(שינוי פשוט של מידע יכול להתבצע באמצעות Behaviors כדוגמת מימוש IOperationBehavior ביתר קלות )

 

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

 

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

 אנו כתבנו Custom channel משלנו והכנסנו אותו ל channel  stack  .

15

ה  Channel הכיל את הלוגיקה כלומר את המימוש של ה Bridge  שמתאם בין ההודעות , הchannel  הינו statefull  הוא זכר את כל המידע מהקריאות הקודמות שדרושות לצורך התאום .  

הפיתרון מכיל את ה class ים הבאים :

7

LogicOrcBinding

הcustom binding  שמכיל את ה binding elements  שלנו .

 

4

 

הגדרנו רק 2 elements  כאשר תשתיות ה wcf  מוסיפות את החסר  בהתאם לקונפיגורציה אם זה security  , relaibale session  וכד

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

 

 
5
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

LogicOrcBindingElement , LogicOrcChannelFactory , LogicOrcChannelListener

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

כאשר יש פרמטרים שצריך להעביר מה Binding  עצמו ,צריך לדאוג להעביר דרכם .

 

   

 

LogicOrcBodyWriter

class עזר פשוט שתפקדו לעזור בלכתוב את ה פרמטרים של הAction בMessage

הClass  מכיל event  בשם  writeBodyCallback שנקרא אוטומטית על ידי המערכת לצורך עדכון הפרמטרים .

 

6

 

LogicOrcChannel

זהו לב המערכת

8

 

בCtor אנו מקבלים Reference ל Channel הבא בstack

 9

אנו נשתמש בReference הזה לשני דברים :

1.להפנות מימוש methods למימוש ב Channel הבאה בstack ב methods שאין לנו צורך לממשן

לדוגמא:

10

2.הפניית הMessage אחרי הטיפול לChannel  הבאה ב stack

 

הmethods  שמטפלות בשליחת הנתונים ל channel הבאה בstack הינן :

public void Send(Message message, TimeSpan timeout) ,

public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)

כאן משתלבת הלוגיקה העסקית של הBridge בשליחה של הודעות לServer ,ניתן לא להעביר את הMessage ל channel הבא ובכך לחסום את ההודעה ניתן להעביר הודעה אחרת או מספר הודעות אחרות ,כמו כן ניתן להעביר את הטיפול ל thread אחר ובזמן שונה להעביר הודעה ל Channel הבא ב Stack .

 

11

 

דוגמא למימוש

פונקצית עזר לבניית Message חדש בהסתמך על העתקת ה Header של ה message  שהתקבל מבChannel הקודם ושינוי ה Action

12

 

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

 

13

 

הMethods שמטפלות בקריאת הנתונים בצורה סינכרונית או אסינכרונית בהתאמה הינן :

public bool TryReceive(TimeSpan timeout, out Message message)

והצמד

public

IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)

public bool EndTryReceive(IAsyncResult result, out Message message)

 

אחרי ששלחנו שתי הודעות Call1 וCall2 ל Client אמו מקבלים גם שתי תשובות אותן אנו צריכים לאחד לתשובה אחת .את הפעולה הזו אנו עושים ב EndTryReceive

14

 

Exception

בזמן הפיתוח אם מבצעים שגיאה בקריאה של ה Contract לדוגמא קוראים ל Action שאיננו נמצא ב contrat של ה Server המערכת נותנת שגיאה מפורטת :

{"The message with Action 'http://tempuri.org/ILogicOrcSample/CallWithWrongAction' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)."}

טעיות בשמות של ה פרמטרים בד"כ יגרמו ל להעברת null בפרמטרים של ה method

 

בדיקות

שתי בדיקות נעשו לצורך ולידציה של הפתרון :

1.בדיקת memory leak שהמערכת לא משאירה אצלה זבל במקרה ונחסמת פקודה מלהגיע ליעדה וכד.על מנת לבצע את הבדיקות עם התוכנית דוגמא יש להוריד את כל ה חלק של ה  Diagnostic מה Configuration files , לבצע את הקריאות הנדרשות בloop ומידי פעם לקרא ל GC.Collect

2.בדיקת ביצועים ש ה Bridge Channel לא פוגע בביצועים כתוצאה מביצוע הלוגיקה שלו

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

קישור לקוד דוגמא:

קוד דוגמא מאוד בסיסי נמצא כאן .

הקוד מבוסס על דוגמא של מיקרוסופט בשם Chunking channel לדוגמא הוכנסו רק הדברים האלמנטריים ביותר לצורך הדגמת הקונספט .

על מנת להשתמש בה יש כמוסן להוסיף לה את כל הקוד הסטנדרטי כגון טיפול ב Timeouts סגירת Channels  ללא exceptions  וכד.

פורסם: Feb 04 2012, 12:17 AM by zvikapeer | with no comments
תגים:, ,
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 8 and 2 and type the answer here:


Enter the numbers above: