Μικρός οδηγός στο Remoting

Έχουν δημοσιευτεί 01 Φεβρουαρίου 06 11:37 μμ | KelMan 

Αυτός είναι ένας σύντομος οδηγός που στοχεύει στο να ξεκινήσει κανείς να ασχοληθεί με το Remoting. Bασίζεται σε υλικό από το MOC Course 2415B, Programming with the Microsoft .NET Framework με δικές μου προσθήκες και επεξηγήσεις. Ο οδηγός χωρίζεται σε δύο μέρη, στο πρώτο μέρος που είναι θεωρητικό και παρουσιάζονται όλα τα concepts και στο δεύτερο μέρος όπου πλέον παρουσιάζεται ο σχετικός κώδικας.

Μέρος Α’

Αν δεν έχετε ξανακούσει τον όρο Remoting, πρόκειται για επικοινωνία μεταξύ
• Objects που βρίσκονται σε διαφορετικά Application Domains
• Objects που βρίσκονται σε διαφορετικά Processes
• Objects που βρίσκονται σε διαφορετικούς υπολογιστές

Το ωραίο είναι ότι το Framework παρέχει έναν ολοκληρωμένο μηχανισμό ο οποίος είναι διαφανής για τον developer και τον απαλλάσσει από την ευθύνη της διαχείρισης της όλης διαδικασίας.

Οι υπηρεσίες που παρέχει το Framework είναι
• Τα Channels, κανάλια επικοινωνίας τα οποία μεταφέρουν τα μηνύματα από object σε object
• Οι Formatters που κωδικοποιούν και αποκωδικοποιούν τα μηνύματα πριν αυτά ταξιδέψουν στα κανάλια
• Τα Proxies που προωθούν τις κλήσεις προς τα remote objects
• Ενεργοποίηση και έλεγχος της διάρκειας ζωής των remote objects

Channels & Formatters

Είπαμε ότι τα κανάλια μεταφέρουν τα μηνύματα από object σε object. Όταν ο client καλεί μια μέθοδο του remote object, οι παράμετροι μαζί με άλλες πληροφορίες σχετικές με τη κλήση μεταφέρονται μέσω του Channel στο remote object και τα αποτελέσματα επιστρέφουν στον client με τον ίδιον τρόπο. Οι Formatters ουσιαστικά κωδικοποιούν και κάνουν serialize τα δεδομένα σε μηνύματα πριν αυτά μεταδοθούν από τα Channels

O Server μπορεί να επιλέξει να χρησιμοποιήσει διάφορα Channels όπως θα δούμε παρακάτω, ωστόσο ισχύουν κάποιοι κανόνες:
• Για να κληθεί ένα remoting object θα πρέπει να έχει γίνει register στον server τουλάχιστον ένα Channel.
• Τα Channels γίνονται register στον server ανά Application Domain. Εφόσον ένα process μπορεί να περιέχει πολλαπλά application domains, όταν κλείσει το process, καταστρέφονται όλα τα Channels
• Κάθε Channel «ακούει» διαφορετική πόρτα, άσχετα με το ποιο application domain βρίσκεται αυτό

Οι clients επικοινωνούν με τα remote objects χρησιμοποιώντας οποιοδήποτε registered channel. Παράλληλα, το remoting infrastructure προσέχει ώστε το remote object να είναι συνδεδεμένο με το κατάλληλο channel όταν ο client προσπαθεί να επικοινωνήσει μαζί του.

Από την άλλη μεριά, ο client είναι που προσδιορίζει το Channel πριν να ξεκινήσει την επικοινωνία. Αυτό μπορεί να γίνει είτε μέσω του application configuration αρχείου, είτε μέσω κώδικα, καλώντας τη μέθοδο RegisterChannel της κλάσης ChannelServices. Τα κανάλια μπορεί να είναι HTPP, TCP ή SMTP ωστόσο ο μηχανισμός είναι pluggable και μπορεί κανείς να υλοποιήσει τα δικά του προσδιορίζοντας διαφορετικό transport και encoding.

Κάθε Channel χρησιμοποιεί ένα default Formatter αλλά μπορούμε κι εδώ να επέμβουμε και να επιλέξουμε κάποιον διαφορετικό. Το HTTP Channel χρησιμοποιεί τον SOAP Formatter, τα μηνύματα γίνονται serialize σε XML και κατόπιν προστίθενται τα ανάλογα SOAP headers. To ΤCP Channel χρησιμοποιεί ένα binary formatter και κάνει serialize τα μηνύματα σε binary stream χρησιμοποιώντας το TCP πρωτόκολλο.

Όπως είπαμε, επιτρέπεται να κάνουμε και δικούς μας συνδυασμούς (πχ HTTP channel με Binary formatter) απλά οι default συνδυασμοί έχουν τους λόγους τους που χρησιμοποιούνται. 

To HTTP Channel με SOAP Formatter περνάει εύκολα από τα Firewalls ενώ το ΤCP Channel με τον binary formatter παρέχει το καλύτερο δυνατό throughoutput.

Ως προς το security, η πιο ασφαλής λύση όταν γίνεται access από το internet ή ένα μη-secure intranet είναι η χρήση HTTP Channel και να γίνονται host τα remote objects από τον IIS ο οποίος παρέχει προστασία μέσω SSL και διάφορους τρόπους authentication σε αντίθεση με το ΤCP Channel το οποίο μπορεί να χρησιμοποιήσει το IPSec μόνο σε private δίκτυο. Διαφορετικά, θα πρέπει να καταφύγει κανείς στο System.Security.Cryptography.

Proxies

To Remoting επιτρέπει την ενεργοποίηση (activation) των remote objects με δύο τρόπους. Server-side και client-side. Server-side activation σημαίνει ότι όταν ένας client προσπαθεί να κάνει access το remote object, δημιουργείται το instance του αυτόματα στον server.  Client-side activation σημαίνει ότι το instance δημιουργείται μόνο κατ’ επιταγή ενός activation request από τον client.

Κάθε φορά που συμβαίνει ένα activation, ο client αποκτά ένα proxy object το οποίο αναλαμβάνει όλα τα διαδικαστικά της remoting επικοινωνίας ενώ ο client νομίζει ότι χρησιμοποιεί ένα τοπικό object. Δηλαδή, το proxy object λειτουργεί ως αντιπρόσωπος του remote object και κάνει αυτόματα forward τα μηνύματα στο remote object.

To Server-side activation υποστηρίζει δύο τρόπους ενεργοποίησης, τον “Single Call” και τον “Singleton”.

Ένα single call object εξυπηρετεί μόνο ένα request και είναι χρήσιμο για περιπτώσεις όπου δεν υπάρχει μεγάλο overhead κατά τη δημιουργία των objects, θέλουμε να υλοποιήσουμε load-balancing μηχανισμούς και, το σημαντικότερο, δεν μιας ενδιαφέρει να κρατάμε state μεταξύ των κλήσεων. Γι αυτόν το λόγο και αυτά τα objects ονομάζονται “stateless objects”.

Ένα singleton object εξυπηρετεί πολλαπλούς clients και πολλαπλά requests τα οποία μπορούν να μοιράζονται ένα κοινό state (λέγονται και “stateful objects”) και φυσικά εδώ δεν υπάρχει το overhead της δημιουργίας των instances.

Το Client-side activation τώρα, γίνεται όταν ο server λαμβάνει ένα αίτημα από τον client (o τρόπος θυμίζει το COM coclass activation). Αυτός ο τρόπος activation κρατάει κοινό state μεταξύ διαδοχικών κλήσεων αλλά per client, δηλαδή έχουμε τόσα instances του remote object στον server, όσα και οι clients που τα χρησιμοποιούν.

Διάρκεια ζωής του remote object

Ένα θέμα που έχει μεγάλη σημασία είναι η διάρκεια ζωής του remote object. Στο Framework έχουμε τον Garbage Collector που είναι υπεύθυνος για να ανακτά τη μνήμη που αφήνουν τα objects που δεν χρησιμοποιούνται πλέον. Το reference counting που είχαμε στο COM είναι ανεπαρκές για remote objects. Απαιτεί τακτικό pinging για να ελεγθεί αν υπάρχει το απέναντι object, δημιουργεί «άσκοπο» traffic και είναι προβληματικό σε αναξιόπιστα δίκτυα.

Στο Framework χρησιμοποιείται ένας μηχανισμός leasing. Κάθε application domain έχει κι από έναν lease manager o οποίος όταν δημιουργείται ένα remote object του παρέχεται ένα lease time. Όταν τελειώσει ο χρόνος αυτός, τότε o remoting μηχανισμός κάνει disconnect το remote object το οποίο το μαζεύει ο GC την επόμενη φορά που θα τρέξει. Το lease time μπορεί να παραταθεί και υπάρχουν διάφοροι μηχανισμοί για να γίνει κάτι τέτοιο.

Object Marshaling

Πριν φτάσουμε στο τέλος του πρώτου μέρους, έχουμε να πούμε για ένα τελευταίο concept το Object Marshaling.

Μέσα στα πλαίσια ενός application domain, τα objects και τα primitive data types μεταφέρονται by reference ή by value. Τα όρια του application domain είναι αυστηρά, όπερ σημαίνει ότι δεν υπάρχει περίπτωση να περάσει πληροφορία από application domain σε application domain. Ωστόσο, όταν καλούμε ένα remote method μέσω του proxy object, χρειάζεται να περάσουν πληροφορίες πέρα από το application domain. Σε όλες τις παρακάτω περιπτώσεις χρειάζεται να μεταφερθούν πληροφορίες μεταξύ application domains:

• Objects ως παράμετροι στην κλήση μεθόδων:

Public Function myRemoteMethod(ByVal myObj As MyRemoteObject) As Integer

• Objects ως επιστρεφόμενες τιμές από κλήσεις μεθόδων:

Public Function myRemoteMethod(ByVal myString As String) As MyRemoteObject

• Objects που είναι properties ή methods από remote objects

myObj.myNestedObject

Ο remoting μηχανισμός του Framework κατατάσσει τα objects σε τρεις κατηγορίες: marshal-by-value, marshal-by-reference και  not-marshaled.

Τα marshal-by-value objects προέρχονται από τύπους και κλάσεις που είναι serializable. Γι αυτόν το λόγο και μπορούν να «περάσουν» αυτούσια στην άλλη μεριά, δηλαδή περνάει ολόκληρο το state του object. Τυπικά, κάτι τέτοιο σημαίνει ότι μειώνονται τα roundtrips. Τα marshal-by-value objects δεν έχουν ταυτότητα ως distributed objects και δεν δημιουργείται proxy object γι αυτά.

Τα marshal-by-reference objects δημιουργούνται όταν ένα ObjRef περνάει από application domain σε application domain. Μόλις ο παραλήπτης λάβει το ObjRef, τότε δημιουργείται το ανάλογο proxy object και τo marshal-by-reference object παραμένει πάντοτε στο application domain που δημιουργήθηκε. Για να μπορεί να γίνει ένα object marshal-by-reference, θα πρέπει να έχει κάνει inherit τη κλάση System.MarshalByRefObject. H χρήση των marshal-by-reference object συνιστά ένα κάποιο overhead στο performance διότι ότι κάνουμε πάνω σε ένα τέτοιο object (όταν χρησιμοποιούμε fields, properties και methods του), γίνεται intercept από το Framework και προωθείται ανάλογα.

Not-marshaled είναι όλα τα objects που δεν ανήκουν στις δύο προηγούμενες κατηγορίες. Όπως αντιλαμβάνεστε, αυτά δεν μπορούν να συμμετέχουν σε ένα remoting σενάριο γιατί είναι υποχρεωμένα να λειτουργούν τοπικά, στο application domain που δημιουργήθηκαν.

Στην επόμενη συνέχεια του άρθρου, θα περάσουμε από τη θεωρία στην πράξη.

 

Δημοσίευση στην κατηγορία:

Σχόλια:

Χωρίς Σχόλια
Έχει απενεργοποιηθεί η προσθήκη σχολίων από ανώνυμα μέλη

Search

Go

Συνδρομές